perm filename LST[2,TES] blob
sn#009897 filedate 1972-08-31 generic text, type T, neo UTF8
COMMENT ⊗ VALID 00050 PAGES
RECORD PAGE DESCRIPTION
00001 00001
00006 00002 .COMMAND CHARACTER "$"
00012 00003 $PORTION MATERIAL
00015 00004 $ss OPERATION
00023 00005 $SS READING THIS MANUAL
00029 00006 PUB will number your pages 1,#2,#3, etc. unless you declare otherwise.
00034 00007 $BEGIN SKIP TO COLUMN 1 VERBATIM
00037 00008 $AFTER TEXT ⊂⊃
00041 00009 $sec TEXT CONVENTIONS
00045 00010 $SS JUSTIFICATION
00053 00011 $ss WORD BREAKS
00056 00012 α-\FILL mode only, and not the first character of a word: a ≤hyphen≥. This means:
00061 00013
00063 00014 $ss CONTROL CHARACTER ACTIVATION
00067 00015 $SS COMPUTED TEXT,BLURT:
00070 00016 $sec MACROS
00073 00017 $ss TEMPLATES
00077 00018 $ss OMISSIONS
00080 00019 $sec EXPRESSIONS
00081 00020 $ss VARIABLES
00087 00021 $ss SIMPLE EXPRESSIONS,SIMPEX:
00090 00022 $ss GENERAL EXPRESSIONS
00092 00023 $sec STATEMENTS
00094 00024 $ss COMPOUND STATEMENT or CLUMP
00097 00025 $SEC DECLARATIONS
00101 00026 $ss PREFACE DECLARATION
00106 00027 $Ss MARGIN CONTROL,MARGS:
00110 00028 $ss PLACE DECLARATION
00114 00029 $ss COUNTER DECLARATION,COUNTERD:
00117 00030 $sec IMPERATIVES
00122 00031 $BEG
00128 00032 $SS PORTION DEMARCATION,PORTIONS:
00131 00033 $SS SEND STATEMENT,SENDS:
00135 00034 $ss RECEIVE STATEMENT
00140 00035 $ss SKIP STATEMENTS,SKIPS:
00144 00036 $ss CONTINUE STATEMENT,CONTI:
00149 00037 $sec COMMENTS
00151 00038 $sec LABELS AND CROSS-REFERENCES
00156 00039 $SKIP
00162 00040 $SEC RESPONSES
00166 00041 $SS TRANSITION RESPONSES,HEDRESP:
00171 00042 $SEC FOOTNOTES
00174 00043 $PORTION APPENDICES
00176 00044 $APP THOROUGHLY EXPLAINED EXAMPLES
00179 00045 $SAPP SAMPLE TABLE OF CONTENTS
00181 00046 $SAPP ONE-LEVEL INDEXES,INDEXIX:
00187 00047 $SAPP TWO-LEVEL INDEXES
00192 00048 $SAPP KWIC INDEXES
00194 00049 $COUNT PAGE PRINTING "I"
00195 00050 $COUNT PAGE PRINTING "i"
00196 ENDMK
⊗;
.COMMAND CHARACTER "$" ;
$TURN ON "{αβ↑↓_[]#\∂←→∞&∪"
$MACRO INS ⊂ONCE NOFILL; PREFACE 0 ; INDENT 0⊃ ;
$MACRO BEG ⊂INS BEGIN SKIP GROUP⊃ ;
$MACRO SYN ⊂ INS
Syntax:
$INS⊃ ;
$TABS 10,20,30,40,50,60,70
$D ← 25 <<FOR ∂>>
$PORTION TITLEPAGE
$INDENT 0,0,0
$BEGIN
$PLACE HEADING
$NOFILL
STANFORD ARTIFICIAL INTELLIGENCE PROJECT→{(↑MONTH)} {YEAR}
OPERATING NOTE 70
$END
$GROUP SKIP 3
$BEGIN
$CENTER
PUB
$SKIP 1
The Document Compiler
$SKIP 3
by
$SKIP 1
Larry Tesler
$END
$SKIP 6
ABSTRACT:
$BREAK
PUB is an advanced text justifier and page formatter intended
primarily for use by programmers.
It can automatically number pages, sections, figures, footnotes, etc. and can
print their numbers in roman numerals as well as in digit or letter form.
It can generate cross references, tables of contents, and indexes.
Page layout is flexible, and allows multiple column output. Line formatting
includes tabs, underlining, superscripts, subscripts, centering, and
justification. Macros programmed in a SAIL-like string-processing language can
generate text to be printed in the document.
The output of the compiler is a file which
can be printed on the terminal, on the line printer, or on microfilm.
$SKIP 5
$ONCE NOFILL
ACKNOWLEDGMENTS:
Les Earnest created the concept of the Document Compiler and specified most of
its capabilities.
Dan Swinehart provided invaluable advice and aid throughout
the development of PUB.
Russ Taylor programmed the FR-80 preprocessor.
This work was supported in part by the Advanced Research Projects Agency of
the Department of Defense under Contract SD 183.
$MACRO SEC(NAME) ⊂ NEXT PAGE NEXT SECTION BEGIN CENTER
$CURRSS ← NULL ; SECNAME ← "PUB" ;
SECTION {!}
$SKIP 1
NAME
$SKIP ; SECNAME ← "NAME" ;
$END SEND CONTENTS ⊂ IF LINES < 10 THEN NEXT PAGE ; SKIP 2 ;
{SECTION!}∂(10)NAME
$SKIP 1
$⊃ SEND INDEX ⊂ }∧NAME%{PAGE!}∨{
$⊃ ⊃ ;
$MACRO SS(NAME,LBL) ⊂ IF LINES<8 THEN NEXT PAGE LBL NEXT SUBSECTION!
$CURRSS ← SUBSECTION! ;
$IF FIRSTSS = NULL THEN FIRSTSS ← CURRSS ELSE LASTSS ← CURRSS ;
$BEGIN NOFILL INDENT 0 SKIP 2
{!} ↓_NAME_↓
$END SEND CONTENTS ⊂
∂(15){SUBSECTION!}∂(25)NAME\∞ ∞.∞ →#{PAGE!}
$⊃ SEND INDEX ⊂ }∧NAME%{PAGE!}∨{
$⊃ ⊃ ;
$COUNT SECTION
$COUNT SUBSECTION IN SECTION PRINTING "!.1"
$FOOTSEP ← "- - - - - - - - - - - - - - - - - - - - - - - - -"
$COUNT APPENDIX ; COUNT SUBAPPENDIX ;
$MACRO YON(LBL) ⊂ "Section " ; SUBSECTION! LBL ⊃
$INDENT 15, 15
$INSERT CONTENTS
$MACRO BEAK ⊂ BEGIN SKIP GROUP PREFACE 0 INDENT 0,15 TABS 12,20 ⊃
$MACRO YAP(LBL) ⊂ "Appendix " ; SUBAPPENDIX! LBL ⊃
$MACRO QUIET ⊂ VERBATIM ⊃
$TITLE AREA FEETING LINE 53
$MACRO PRINSECS ⊂ PLACE FEETING CENTER
$(IF FIRSTSS = NULL THEN CURRSS ELSE IF LASTSS=NULL THEN FIRSTSS ELSE
$FIRSTSS &" - "& LASTSS) ; BREAK ;
$FIRSTSS ← LASTSS ← NULL ⊃
$ODD HEADING (SAILON-70,{SECNAME},Page {PAGE!})
$EVEN HEADING (Page {PAGE!},{SECNAME},SAILON-70)
$AFTER TEXT ⊂PRINSECS⊃
$SECNAME ← FIRSTSS ← LASTSS ← CURRSS ← NULL ;
$AT "≤" PHR "≥" ⊂ }PHR{ SEND INDEX ⊂ }∧PHR%{PAGE!}∨{⊃ ; ⊃ ;
$PORTION MATERIAL
$COUNT PAGE
$SEC INTRODUCTION
$SS PURPOSE
PUB is a compiler which translates a ↓_manuscript_↓ into a ↓_document_↓.
A "≤manuscript≥" is an SOS file containing the text of a publication interspersed
with control characters and commands. The function of the ↓_compiler_↓ is to arrange
this text on formatted pages under the direction of the control characters and
commands.
Output is written on a ".DOC" file known as the "≤document≥". TYPE, SPOOL or PRINT it.
Under certain conditions, the document can be edited with TECO (see {YON DEV}), but it
is wiser to make corrections in the manuscript and then rerun the compiler.
$BEG
MANUSCRIPT α→α→α→α→α→α→α→α→ DOCUMENT
###########COMPILER
$END
$ss CAPABILITIES
PUB provides the usual capabilities of a simple text-justifier, including:
$BEG
>Page numbering
>Optional justification to the right margin
>Centering of titles
>Headings and footings
>Control of Spacing and Indentation
>Underlining
$END
In addition, it features advanced documentation capabilities, such as:
$BEG
>Columnar output
>Footnote placement
>Macros
>Index Generation
>Table of contents generation
>Cross-reference to a variable target
>Automatic numbering of equations, tables, notes, etc
>Superscripts and Subscripts
>Microfilm Output
$END
The command language is a dialect of SAIL Algol, providing the user with:
$BEG
>Block structure
>Conditional command execution
>Conditional text inclusion
>Arithmetic and String calculations
>Embedded Source Files
$END
$ss OPERATION
The compiler is "two-pass". The first pass interprets the manuscript and outputs
several intermediate files with extensions ".≤PUG≥", ".≤PUZ≥", and ".≤PUI≥". The second pass
is a separate program automatically called which makes one pass through the ".PUI" files and
produces the document. The ".PUG" and ".PUZ" files are automatically deleted
at the end of Pass One. The ".PUI" files are read by Pass Two, then deleted
(unless deletion is waived by a switch setting -- see below).
The first pass typically requires 40K of core and runs at the
rate of 15 pages per minute. The second pass needs 18K
and runs at 50 pages per minute. If the system should crash during Pass Two,
and you wish to restart without rerunning Pass One, R ≤PUB2≥.
"R PUB2" also gives you an opportunity to specify a different output device
than originally requested.
You may run the document compiler with or without ≤RPG≥. A manuscript file
which is ".PUB" or a document file extension which is ".DOC" need not be
mentioned. Examples:
$skip
$BEG
$TABS 30, 45, 60
↓_command typed_↓\↓_input file_↓\↓_output file_↓\↓_switches_↓
.↓_COM FOO_↓\FOO.PUB\FOO.DOC
.↓_COM FOOα←BAZ_↓\BAZ.PUB\FOO.DOC
.↓_COM /PUB FOO.OOFα←BAZ.ZAB_↓\BAZ.ZAB\FOO.OOF
.↓_COM /PUB FOO.OOF_↓\FOO.OOF\FOO.DOC
.↓_COM FOO(DN)_↓\FOO.PUB\FOO.DOC\/D /N
.↓_R PUB_↓
α*↓_FOO/D/N_↓\FOO.PUB\FOO.DOC\/D /N
$END
Do not specify more than one input file nor more than one output file.
Multiple input files are handled using the REQUIRE statement (see {YON REQR}).
WARNING (RPG users): If in addition to file X.PUB you have a file X.SAI (or
X.FAI, etc.) and if you type "COM X", RPG will do a SAIL (or FAIL) compilation.
SOLUTION: Type "COM#X.PUB".
FURTHER WARNING (RPG users): If you have a file
X.REL which is newer than X.PUB, then RPG won't do any compilation.
SOLUTION: Type "COM#/COM#X.PUB".
Presently available ≤switches≥ are:
$BEAK
→nS\\Change intra-paragraph line spread: 1S=Single Space, 2S=Double Space, etc
→B\\Big Document -- allocates hashed space for 3000 identifiers instead of 1000
→H\\Huge Document -- allocates maximum symbol table space (8191)
→D\\DEBUG -- prints approximate source file line numbers alongside the output
→L\\Line Printer output planned (Default)
→M\\Microfilm output planned (produces FR80 command file -- see {YON DEV})
→T\\Terminal output planned (may produce different output than /L)
→Y\\Yes! Automatically delete ".PUI" files after Pass 2 (Default)
→N\\No! Don't delete them (thus allowing Pass 2 to be re-run with a different DEVICE)
→A\\Ask me whether to delete them when it's time.
→Z\\Compiler Debug: see compiler (PUB.SAI[2,TES])
$END
$SS COMPILER OUTPUT
During Pass one, whenever PUB reads a "Page Mark" or Form Feed,
it types out the manuscript page number. During Pass Two, whenever
PUB writes a Form Feed, it types out a count of the number of
output pages so far.
During Pass One, PUB also types out ≤error messages≥.
After each message, an arrow (α→) or a question mark (α?) is typed out.
You may then respond as in SAIL. If you are not familiar with SAIL,
here is a summary of responses:
$beak
→<CR>\\Continue compiling after this error.
→<LF>\\Continue compiling, and after subsequent errors, continue automatically.
\NOTE: The above two responses are not valid after "?"
→E<file><CR>\\Edit file <file>.
→E<CR>\\(RPG only) Edit the manuscript file.
→S<CR>\\Start Over.
$end
In DEBUG mode (the /D switch), some error messages are also output in the
right margin of the document.
Whenever PUB prints a line number in an error message or in the right margin
of the document, it is of the form:
$INS
<file id><line no.>/<page no.>[<macro line no.>/<macro page no.>]
If the line is from the manuscript, then <file#id> is empty. If it is from
another file (such as one of those ".PUG" files mentioned above), then
<file#id> is the first three letters of the first name of that file.
If the file is in SOS format, then the <line#no.> is always five digits,
including leading zeroes if necessary. If it is from a TECO or TVEDIT file,
then PUB generates line numbers 1,#2,#3, etc. without leading zeroes.
If it is from a ".PUG" file, then the <line#no.> is the line number/βpage number
of a relevant line in your manuscript or in some other source file.
If a macro was being expanded, the line number and page number of its definition
are noted within square brackets.
The file that contained the definition is not noted, so if
can't find it in your manuscript, it probably came from PUBSTD.DFS, the PUB
standard macro file, or from one of your REQUIRE files (see {YON REQR}).
Examples:
$BEG
02300/10 Manuscript file, page 10, line 2300 (SOS)
IND02300/10/1 INDEX.PUG file, page 1, comes from Manuscript 2300/10
PUB25/1 PUB Standard Macro File, Page 1, Line 25 (TVEDIT)
$END
$SS READING THIS MANUAL
This manual is ordered such that as soon as you have learned enough of the
system to solve your particular problem, you can skip the rest of the manual.
Read at least through {YON PGPH} before making any such assumption.
In describing the ≤syntax of PUB commands≥, the following meta-linguistic
symbolism is employed:
$BEAK
→<...>\\These brackets delimit the name of a syntactic entity
→[...]\\These delimit optional components of the command
→...|...\\This character separates alternatives for the same command component
$END
Cross-references in this document are always to subsections. Subsection
numbers are printed at the bottom of each page.
$SS TUTORIAL FOR BEGINNERS
PUB is a string processing language. Characters can be formed into words,
words into lines, lines into paragraphs, paragraphs into columns,
columns into "areas" (such as the title areas at the top and bottom of
the page), areas into pages, pages into sections,
sections into "portions" (such as the Table of Contents or the
Appendices), and portions into a document. The methods of bulding larger
units from smaller ones are flexible and under control of the programmer.
The most trivial use of PUB is to create a document that is exactly identical
to the manuscript, adding only headings and footings. PUB assumes that
the format of each output page is as follows. The first
three lines are a Heading area of which only the first is usually used.
The next 48 lines (lines 4 to 51) are the Text area. Line 52 is
blank and line 53 is a Footing area. The Footing area is for page numbers and
other reference information, not for footnotes.
(Footnotes are placed inside the Text area,
towards its bottom).
The width of each page is assumed to be 69 characters. It is assumed that
there is only one column of text output. Therefore, the longest an
output line can be is 69 characters.
The number of lines in each area, the number of columns of text, and the
number of characters in each column may be changed by declaration.
See {YON AREAD} and {YON PGFRM} for details. If all you want to do is
widen the page, e.g., to 75 characters, then make the following line the first
of the manuscript:
$ins
.PAGE FRAME 53 HIGH 75 WIDE
The "Dot" in column one indicates that this line is a Command Line for PUB to obey
and should not be printed in the document. If you would rather a different
character in column one served for this purpose, see {YON COMCHR}.
PUB assumes that you want no headings and footings. It will leave
the heading and footing areas blank unless you specify otherwise.
The simplest way to specify headings and footings is with the standard
macros "EVERY HEADING" and "EVERY FOOTING".
These macros can specify a title for the left edge, center, and right edge
of the heading area and the footing area. For example, the macro call:
$INS
.EVERY HEADING(PRELIMINARY REPORT,PARACYBERNETIC PHENOMENA,1972)
will print on the top line of every page the three titles shown.
To make the top line of every page display the title "PRELIMINARY REPORT" on the left
and the current date on the right, use:
$INS
.EVERY HEADING(PRELIMINARY REPORT, ,α{DATE})
The consecutive commas indicate that the center is empty. The curly
brackets around the word DATE specify that DATE is not a title to be
printed but rather a variable to be evaluated.
To make the number of each page appear bottom center, use:
$INS
.EVERY FOOTING(,α{PAGE},)
To learn about fancier headings and footings, you will have to read most
of this document, especially {YON TITLES} and {YON HEDRESP}.
$BREAK
PUB will number your pages 1,#2,#3, etc. unless you declare otherwise.
To learn how, see {YON COUNTERD}.
A new page of output will be started for one of two reasons: the previous
page is full, or a page-changing command is executed. The most common
page-changing command is:
$INS
.NEXT PAGE
This always starts a new page, even if one was just started and nothing
is on it yet. To start a new page only if there is something on the
current page, use:
$INS
.SKIP TO COLUMN 1
To leave a few blank lines in the document, use:
$INS
.GROUP SKIP 10
The SKIP command is described in {YON SKIPS}.
PUB processes text a paragraph at a time. The usual way to indicate the
end of a paragraph in your manuscript is by a blank line (that is,
just a CR and LF).
Oher ways are discussed elsewhere in this manual, beginning at
{YON PGPH}.
Usually,
PUB packs a paragraph as tightly as possible by filling up each output
line with words before beginning a new line. This is called "≤filling≥".
Then PUB inserts extra spaces between words to eliminate a ragged right
edge from the paragraph. This is called "≤justifying≥".
PUB will not indent the first line of paragraphs
unless an indent command appears in the manuscript, e.g.:
$INS
.INDENT 6
To learn more about indentation and related matters, see {YON INDS} through
{YON AREAD}.
PUB assumes you would like your text lines filled out and justified. You
can selectively exempt blocks of your manuscript from this fate.
Each such block must be delimited by ".BEGIN" and ".END".
After "BEGIN", specify a formatting mode to persist for the duration of the
block. Examples:
$BEG
↓_Fill, but don't Justify Don't even fill Copy verbatim_↓
.BEGIN NOJUST .BEGIN NOFILL .BEGIN VERBATIM
... ... ...
.END .END .END
$END
In "≤NOJUST≥" mode, lines will be filled but not justified. In "≤NOFILL≥"
and "≤VERBATIM≥" modes, they will not even be filled. The difference
between NOFILL and VERBATIM is that VERBATIM is both faster and dumber.
It is faster because it copies the lines of the manuscript to the
document without looking at them, except to see if there is a dot in
column one. It is dumber because it does not recognize text control
characters that PUB normally recognizes, and it does not reformat in
any way. Thus, VERBATIM is used to copy blocks of manuscript that are
arlready formatted perfectly.
Filling allows the manuscript to be quite ragged, a great convenience
in editing. Short lines are lengthened and long lines are shortened.
Be careful in NOFILL or VERBATIM mode that no manuscript line is
longer than 69 characters (or whatever limit you have declared),
or some of it will be lost and an error message given.
$SS SAMPLE COMPILATION
You now know enough to use PUB for simple purposes. The next three pages
show a sample manuscript and the document that PUB produced from it.
$BEGIN SKIP TO COLUMN 1 VERBATIM
.EVERY HEADING(DAN MATION,PARACYBERNETIC PHENOMENA,{DATE})
.EVERY FOOTING(,{PAGE},)
.INDENT 6
.BEGIN VERBATIM
.GROUP SKIP 20
PARACYBERNETIC PHENOMENA
BY DAN MATION
.END
.NEXT PAGE
It has been observed that the Sigma 3 in Horsetown, Mass. and the
CDC 6600 in Liverless, Cal. tend to have parity errors at the same
time. When records were compared by
Miss Minnie Messer, Director of the Horsetown Chamber of Commerce
Computation Facility,
and Mr. Solomon Crunch of Liverless Hospital's Organ-Transplant
Inventory Project, it was shown that
the correlation of parity error occurrences was 0.8, with a
probability of random coincidence of <.00000001.
Miss Messer and Mr. Crunch revealed these discoveries at the
Universal Users Union meeting in Cranchville, Tenn. after they
arrived two hours late for Mr. Crunch's scheduled talk there.
They said that in the excitement of discovery
the meeting slipped their minds.
This report has motivated this author to undertake
a wider survey to determine if similar
phenomena have occurred elsewhere. The author has
solicited Miss Messer's assistance in this survey,
but without the cooperation of the entire computing community,
it is unlikely that sufficient
data
can be collected. Therefore, we request that interested
parties tabulate the exact times of occurrence of parity
errors on their computer during the 7 day period
1200 April 18 to 1200 April 25 and send it to:
.BEGIN NOFILL
Paracybernetic Society
c/o Dan Mation
Boise Institute of Technology
Boise, Idaho
.END
Results of the study will be presented at the next UUU meeting
in December.
$END
$AFTER TEXT ⊂⊃
$COMMAND CHARACTER "." ;
.BEGIN
.EVERY HEADING(DAN MATION,PARACYBERNETIC PHENOMENA,|January 15,1972|)
.FAKPG←1 ; INDENT 6,0 ; EVERY FOOTING(,{FAKPG},) ;
.NEXT PAGE
.BEGIN VERBATIM
.GROUP SKIP 20
PARACYBERNETIC PHENOMENA
BY DAN MATION
.END
.FAKPG ← 2 ;
.NEXT PAGE
It has been observed that the Sigma 3 in Horsetown, Mass. and the
CDC 6600 in Liverless, Cal. tend to have parity errors at the same
time. When records were compared by
Miss Minnie Messer, Director of the Horsetown Chamber of Commerce
Computation Facility,
and Mr. Solomon Crunch of Liverless Hospital's Organ-Transplant
Inventory Project, it was shown that
the correlation of parity error occurrences was 0.8, with a
probability of random coincidence of <.00000001.
Miss Messer and Mr. Crunch revealed these discoveries at the
Universal Users Union meeting in Cranchville, Tenn. after they
arrived two hours late for Mr. Crunch's scheduled talk there.
They said that in the excitement of discovery
the meeting slipped their minds.
This report has motivated this author to undertake
a wider survey to determine if similar
phenomena have occurred elsewhere. The author has
solicited Miss Messer's assistance in this survey,
but without the cooperation of the entire computing community,
it is unlikely that sufficient
data
can be collected. Therefore, we request that interested
parties tabulate the exact times of occurrence of parity
errors on their computer during the 7 day period
1200 April 18 to 1200 April 25 and send it to:
.BEGIN NOFILL
≤Paracybernetic Society≥
c/o Dan Mation
Boise Institute of Technology
Boise, Idaho
.END
Results of the study will be presented at the next UUU meeting
in December.
.END COMMAND CHARACTER "$" ;
$ODD HEADING (SAILON-70,{SECNAME},Page {PAGE!})
$EVEN HEADING (Page {PAGE!},{SECNAME},SAILON-70)
$EVERY FOOTING ()
$sec TEXT CONVENTIONS
$ss ILLEGAL CHARACTERS
$AFTER TEXT ⊂PRINSECS⊃
If the following characters occur in the manuscript, they may cause problems:
$BEAK CRBREAK
→'177\\Rubout
→'175\\Altmode
→'13\\Vertical Tab
$end
These characters are ignored in the manuscript:
$BEAK CRBREAK
→'0\\Null
→'14\\Form Feed (except after LF, where it is a page mark)
$end
A manuscript prepared using SOS or TVEDIT is legitimate if it has no vertical tabs.
If it is prepared using TECO, be sure as well that every line ends with CR LF.
Tabs are expanded to the appropriate number of spaces, as in the line editor.
$SS COMMAND AND TEXT LINES,COMCHR:
Every line with a dot (".") in column 1 is processed as a ↓_≤command line≥_↓. Every
other line is processed as a ↓_≤text line≥_↓.
If you would prefer a different character to introduce command lines, e.g.,
α$, use the command:
$ins
COMMAND CHARACTER "$" ;
$SS PARAGRAPHING,PGPH:
The text is processed in logical units called "paragraphs". A paragraph is
the accumulation of words from one or more text lines, terminated by the
occurrence of a ↓_≤paragraph break≥_↓.
A ↓_paragraph break_↓ can be caused by the command BREAK as well as by several
other commands. In addition, a paragraph break can be caused by signals in
the text.
Paragraphing conventions can be varied by the use of various mode and switch
settings.
$SS FILL MODE
In FILL mode, the compiler puts as many words as can fit on each output line
before beginning a new line -- each line is "filled" with words.
For convenience of exposition, names have been given to the parts of the
output paragraph in FILL mode. The first line is called the ↓_≤crown≥_↓,
and the rest of the lines are called the ↓_≤vest≥_↓. It is common to
indent the crown and not the vest, or vice versa, or to indent them different
amounts. The last line of the vest is called the ↓_≤hem≥_↓. While the other
lines of the paragraph can be subject to justification, the hem line is never
justified.
$SS JUSTIFICATION
$once nojust
In FILL mode, whether
or not output lines are justified
to the right margin is determined by the setting
of the "≤ADJUST≥-≤NOJUST≥" switch; but the hem line is never
justified in any case.
$SS BREAKING AT BLANK LINES
In FILL mode, a BREAK is caused by every blank line (just CR-LF).
Redundant blank lines have no effect.
To disable this response, see {YON TEXTRESP}.
$SS BREAKING AT TABS
Tabs are converted to an appropriate number of spaces by PUB. If you
would like a single tab at the beginning of a text line to cause a
paragraph break, put this command at the beginning of your manuscript:
$INS
.≤TABBREAK≥
This makes text lines that are indented exactly 8 spaces cause a break.
Since an initial TAB is converted to 8 spaces, it will also break.
The inverse of TABBREAK is ≤TABSPACE≥.
$SS BREAKING AT CARRIAGE-RETURNS
In FILL mode, PUB usually converts every ≤carriage-return≥ at the end
of a text line to a space. If it is at the end of a sentence, it converts
the carriage-return to two spaces.
If you would rather that every carriage-
return ending a text line caused a paragraph break, use this command:
$INS
.≤CRBREAK≥
The inverse of CRBREAK is ≤CRSPACE≥.
$SS NOFILL MODE
In NOFILL
mode, one input line produces one output line, even if it falls far short of
the right margin; if the line is too long, characters will be lost.
Every carriage-return ending a text line in NOFILL mode causes a paragraph
break. The commands ADJUST, CRSPACE, and TABBREAK do not affect this mode.
NOFILL mode has several variations, which differ mainly in the final treatment
of the output line:
$skip once nofill
≤NOFILL≥: (Standard variation) No special treatment.
$skip once center
≤CENTER≥: Center the output line between the margins.
$skip once flush right
≤FLUSH RIGHT≥: Shove it against the right margin.
$skip once flush left
≤FLUSH LEFT≥: Shove it against the left margin.
$skip once justjust indent 0
≤JUSTJUST≥: Justify it by the insertion of spaces.
$skip begin verbatim
VERBATIM: Copy text lines to output exactly as written,
without changing
indentations. Ignore all control characters {α↑[#]&↓β\∂-∞←→.
Dot in column 1 still signals a command line.
This mode speeds text processing
when no formatting is needed.
$END
≤SUPERIMPOSE [n]≥: Suppress the LF after each line, except every n'th line.
$BEGIN indent 0 superimpose 2
α< α↑ α< α! α≡ α∩ α⊂ α~ α% α7 αZ
α| α↓ α> α? α/ α∪ α⊃ α. α\ α- α-
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
$END
$SS HORIZONTAL SPACE COMPACTION
In ≤COMPACT≥ mode, redundant spaces in the input line are discarded. In
≤RETAIN≥ mode, they are retained.
More precisely, in COMPACT mode, a sequence of two or more spaces is
reduced to one space, except at the end of a sentence, where it is only
reduced to two spaces, and at the beginning of a text line,
where all spaces are discarded. Of course, spaces may be re-inserted during
justification.
$SS VERTICAL GROUPING
In ≤GROUP≥ mode, all output lines are forced to appear in an unbroken column.
Its inverse is ≤APART≥ mode.
If the bottom of the output page is encountered while in GROUP mode, the
whole group is moved to the top of the next column or page.
It is unwise
to use GROUP mode for more than a few lines that must appear undivided in the
output. Example:
$BEG
.GROUP
EQUATION 6
m = vt
.APART
$END CONTINUE
This would prevent "Equation 6" from appearing at the bottom of one page
and "m#=#vt" at the top of the next.
$SS MODE AND SWITCH SETTING COMMANDS
The commands that select the paragraphing mode are FILL, NOFILL, CENTER, FLUSH RIGHT,
FLUSH LEFT, JUSTJUST, VERBATIM, and SUPERIMPOSE [n],
where n [optional] is any "SAIL" expression.
The commands ADJUST and NOJUST set the FILL-mode justification switch.
TABBREAK, TABSPACE, CRBREAK, and CRSPACE control the reaction to initial tabs
and to carriage-returns in FILL mode.
The commands RETAIN and COMPACT, GROUP and APART select the space compaction
and column grouping modes.
At the outset of compilation, the settings in force are:
$ins
.FILL\ADJUST\TABSPACE\CRSPACE\RETAIN\APART
WARNING: Switching to NOFILL or to any of its variations automatically switches to
RETAIN mode. This can be overridden by following the command by COMPACT.
$ss WORD BREAKS
The compiler processes the input paragraph in units called ↓_words_↓. A "word"
is roughly defined as a sequence of consecutive visible characters. More
precisely, the compiler concatenates characters into a word until the occurrence
of a ↓_word break_↓.
A word break is normally signalled by any of the following in a text line:
$BEG
>A space (or a sequence of spaces)
>A carriage-return (the end of an input line)
>The control character β, if activated (as well as some others)
$END
Word breaks serve two functions.
(1)#FILLING:##In generating an output paragraph, the compiler puts as many words as can
fit on each line before beginning a new line. The paragraph will only be
divided for this purpose at word breaks.
(2)#JUSTIFYING:##During ≤justification≥, extra spaces will only be inserted at word breaks.
$ss CONTROL FUNCTIONS
Several control functions can be invoked by ≤control characters≥ in the text
line. The user can choose the characters he wishes to serve these functions.
For simplicity of exposition, a suggested character has been designated for
each function.
The following control functions are available. If the description states:
"BLA mode only", then in other modes, the character is treated no differently
than an alphanumeric.
$BEGIN narrow 10 indent 0,5
αβ\Cause a word αβreak.
αα\Pretend the next character is ααlphanumeric (this lets you slip in control characters);
α#\Same as αα<space>; sneaks spaces into words.
. α! α?\FILL mode only, and only at the end of a word: marks the end of a
sentence. This means:
\(1)#If followed by two or more spaces, COMPACTion only reduces the spaces to two
instead of one.
$ONCE PREFACE 0
\(2)#If followed by a carriage-return, replaces the CR by two spaces instead of one.
α-\FILL mode only, and not the first character of a word: a ≤hyphen≥. This means:
\(1)#If at the end of a line, prevents the word break that usually occurs there.
$ONCE PREFACE 0
\(2)#Otherwise, permits the word to be broken after the hyphen in case it overfills
the output line.
α\\≤TAB≥. Insert spaces up to the next tab stop set by the TABS command (see {YON TABS}).
α∂+n\MOVE RIGHT. Leave n spaces in the output line.
α∂-n\MOVE LEFT n characters. Create new characters (these due to Jerry Agin):
~∂-1>∂-1_ ~∂-1( O∂-1α- O∂-1| ~∂-1V.
α∂n\≤TAB≥. Insert spaces up to but not including
the n'th character position from the left margin (flush left is n=1).
Both kinds of TAB (α\ and α∂n) inhibit insertion of all justification spaces to
their left.
\For α∂n and α∂+n, n may be any "SAIL" expression enclosed in parentheses. In
the case of a single letter variable or a one-digit number, the parentheses
may be omitted.
RESTRICTION... α∂(<expression>) may not appear as the last thing on a text line.
α→\≤Right Flush≥. If a α\ or α∂n occurs later in the line,
slide the text that is between here and there flush against the column
designated by the tab. Otherwise, →slide the rest of this paragraph
against the right margin, inhibiting justification.
α←\≤Center≥. If a α\ or α∂n occurs later in the line, center
the text that is between here and there halfway between the current column
and the column designated by the tab. Otherwise, center the following text
between the margins, inhibiting justification.
α∞x\Repeat. `x' is any character. If α∞x precedes α\, α∂+, α∂n, α→, or α←,
then use the character x instead of spaces as filler to the left of the affected
text (i.e., α∞.α\ puts ....α. up to the tab column).
α∞xα∞yα∞z...\Use the repeating string xyzxyz..α. as filler.
α↓α_...α_α↓\≤Underline≥. ↓_In the text between brackets,
every visible character is underlined._↓
"_" is only a control character when paired with "α↓".
If you want spaces underlined as well in a title, simply ↓_replace_each_space_by_an_underbar_↓.
α∪\α∪nderline one word. The following ∪word (consisting of letters and digits only)
is ≤underline≥d.
απ\απrint a wierd character. The line printer and FR-80 have these but your terminal doesn't.
$BEGIN NOFILL TURN ON "π" INDENT 25 ; D ← 45 ;
↓_To get_↓∞.∂D↓_Write_↓
π. (center dot)∂Dαπα.
πg (gamma)∂DαπαG or απαg
π∂ (apple delta)∂Dαπα∂
π~ (integral)∂Dαπα~ (tilde)
π- (απlus-minus)∂Dαπα-
π+ (circle plus)∂Dαπα+
$END
α{\Switch to ≤Command Processing≥. To return to text processing, use α}. See
{YON BLURT}.
α↓x\≤Subscript≥. The text x is ↓[lowered a line] (an extra line is reserved
for it). x may be any single character except "[" or "_", or may be a
sequence of characters bracketed between [...] . A subscript must appear all
on one line.
α↑x\≤Superscript≥. Analogous to Subscript, except x may also be the single
character "_". Collectively, ↑[superscripts] and ↓[subscripts] are called
↓_somescripts_↓.
\These may combine and nest in interesting ways. Super/subscripts may not
nest more deeply than 4.
αx&y\Align. "&" is only considered a control character if it is the first
character following a somescript x. Its effect is to align the leftmost
characters of x and y by backspacing after printing x and before printing y,
and to align the rightmost characters by forward spacing to the end of the
longer of x and y when done. x must be a somescript. y may be any single
character except "[", "α↑", or "α↓", or may be another somescript, or may be
any sequence of characters enclosed between [...] . Examples:
$END
$BEG
↓_To get_↓∞.\↓_Write_↓\↓_To get_↓∞.\↓_Write_↓
$PREFACE 1
x↑j&↓i\xα↑j&α↓i\↑_&y↓[i+j]&↑[ 2]\α↑_&yα↓[i+j]&α↑[ 2]
x↓i↑2\xα↓iα↑2\↓[ t]&[SUM]\α↓[ t]&[SUM]
↓x&∃\α↓x&∃\x↑i↑2\xα↑iα↑2
↑.&t\α↑.&t\x↑[i↑2]\xα↑[iα↑2]
$END
$ss CONTROL CHARACTER ACTIVATION
At the outset of compilation, the only control characters recognized are
the punctuators ".", "!", and "?" when they appear at the end of a word,
and hyphen ("-") when it appears in the middle of a word.
NOTE: Not even "α{" is recognized unless you activate it. However, "}" is
permanently active, because it is not a text control character
but really a command langauge delimiter.
To turn on any control function using its suggested character ("αα"
for example), use the command:
$ins
.≤TURN ON≥ "αα"
To activate the control function using a different character, such as "%" or "αβ", write:
$BEG
.TURN ON "%" FOR "αα"
.TURN ON "αβ" FOR "αα"
$END CONTINUE
To de-activate a control character, such as "?" or "%", use:
$BEG
.≤TURN OFF≥ "?"
.TURN OFF "%"
$END
One TURN command may have several operands separated by commas:
$INS
.TURN ON "%" FOR "αα", "@" FOR "α←", "α→", "α\"
$INS
.TURN ON "α↑", "α↓", "α[", "α]", "α_", "α&"
The latter may be abbreviated:
$INS
.TURN ON "α↑α↓α[α]α_α&"
There is a subtle problem that arises when control characters have been turned on
inside a macro and the macro wants to turn off only the ones that weren't on
previously.
If it has done a TURN#ON#"α↑", for example,
it can not undo it with TURN#OFF#"α↑", for that would
always TURN#it OFF whether or not it was originally on.
There are two ways to do it right. One is to use
block structure (see {YON BLOCKS}), but sometimes this is impossible, because
blocks cause paragraph breaks. The other way is to use the command TURN#ON|OFF
without arguments. Its effect is to cancel the previous TURN#ON|OFF that
had arguments, was in the current block, and has not yet been cancelled.
For purposes of smooth exposition, in the rest of this manual it is assumed
that you have turned on all the control functions and used all the suggested
characters for them.
Remember, though, that only the punctuators are turned on unless you command
otherwise!
It is recommended that you don't turn on any characters except in short blocks
where you know you'll remember they're on. Ideal places are inside macro
bodies (See {YON MACS}).
$SS COMPUTED TEXT,BLURT:
The control character "α{" will switch to command processing right in the middle
of a text line. This allows the execution of any PUB commands without first
causing either a paragraph break or a word break. If you want a word break
before the α{, force it by means of a αβ or a space.
The command most commonly executed after "α{" is the ↓_Computed Text Command_↓.
A variable, a constant, or a ∪parenthesized expression
occurring in isolation is evaluated and its
string value is then scanned by the text scanner as text. Example:
$skip ins
A = α{Aα}, and B = α↓_α{(2+2)α}_α↓.
$BREAK
If the value of A was the string "α∪3", this would output:
$SKIP INS
A = {"∪3"}, and B = ↓_{(2+2)}_↓.
$BREAK
Caution: If a α{...α} construct extends onto a second input line, be sure to
begin the continuation line with a "." -- or you won't be in the command
scanner!
Caution: A string constant following the word BEGIN is considered a block name,
as in SAIL, and not computed text. If you put computed text
after BEGIN, precede it by a semicolon.
Note that a "α}" (which can not be TURNed ON and OFF) switches to text processing from
command processing at any time.
This allows a ↓_Short Text Line_↓ to be put right into a command line:
$ins
.NOFILL α}I am a short text line.α{BREAK FILL
which is the compact equivalent of:
$BEG
.NOFILL
I am a short text line.
.FILL
$END
To summarize, there are two ways to switch from command to ≤text processing≥:
$BEG
>New line without "." in column 1
>α}
$END CONTINUE
and two ways to switch from text processing to ≤command processing≥:
$BEG
>New line with "." in column 1
>α{
$END
$sec MACROS
$SS CALLING A MACRO FROM A COMMAND LINE,MACS:
It is common to repeat an identical sequence of commands many times in a manuscript, e.g.,
$ins
.FILL ADJUST COMPACT TURN ON "α∂α{αααβ"
You could define the following macro:
$ins
.MACRO FAC ⊂ FILL ADJUST COMPACT TURN ON "α∂α{αααβ" ⊃
and then whenever you want the whole sequence executed, write simply:
$ins
.FAC
The body of the macro enclosed between ⊂ and ⊃ is substituted for its name and then scanned by the
command scanner.
A macro may also have arguments:
$ins
.MACRO T(CHR) ⊂ NOFILL TURN ON "CHR" ⊃
which when called by:
$ins
.T(αα)
expands to:
$ins
. NOFILL TURN ON "αα"
$SS CALLING A MACRO FROM A TEXT LINE
It is also common to repeat an awkward sequence of control characters many
times in the manuscript, e.g.,
$ins
Xα↑i&α↓[j,k]
You could define the following macro:
$ins
.MACRO XIJK ⊂"Xα↑i&α↓[j,k]"⊃
but to call it you must get to the command scanner:
$ins
α{XIJKα}
When the body is substituted for the name,
this becomes a string constant inside curly brackets:
$INS
α{"Xα↑i&α↓[j,k]"}
so it is considered computed text and is scanned by the text scanner,
producing the output:
$SKIP INS
X↑i&↓[j,k]
Again, parameters can be used:
$ins
.MACRO S(X,I,J,K) ⊂"Xα↑i&α↓[j,k]"⊃
If called by α{X(i,j,k)α} this would expand to the same as above, but called by
$ins
α{S(Y,t,t1,URG)}
it would expand to "Yα↑t&α↓[t1,URG]" which would output:
$ins
Y↑t&↓[t1,URG]
Some macros are declared for you in an automatically loaded file ≤PUBSTD.DFS≥
(see {YON TITLES}). Other useful macros are declared in a file ≤PUBMAC.DFS≥
that you can REQUIRE (see {YON REQR}) to be loaded; they are described in
PUBMAC.TES[UP,DOC].
$ss TEMPLATES
A "template" occurs as a part of several commands, including the macro declaration,
and requires some explanation. Its purpose is to store
away a piece of program for later, instead of immediate, execution.
$syn
⊂ <piece of program> ⊃
The <piece of program> may include other templates, and may span several lines.
However, several rules should be followed:
(1) The template should begin and end on a command line.
(2) Every ∃ or unpaired ⊂ or ⊃ must be preceded by a ∃.
(3) People who change COMMAND CHARACTER in mid-manuscript, note:
the character beginning command lines within the template must be the one
current at the time of declaration -- not the one current when you invoke it later.
$ss MACRO DECLARATION
$syn
MACRO <name> [<formal parameters>] [;] <template>
The <name> may be one or two identifiers. The <formal parameters> if
present, are in the following form:
$ins
( [ε]<identifier> , ... )
Each parameter preceded by ε is a ↓_value_↓ parameter, and when called,
the actual parameter that corresponds is εvaluated and the value is
substituted for each occurrence in the <template> of the <id>.
Every other parameter is a ↓_literal_↓ parameter, and the actual parameter
is substituted unevaluated. Example:
$ins
.MACRO PLUG IN(X, εY) ⊂ "X --- Y" ⊃
If called by:
α{PLUG IN(Peter Pauper, V)}
where V is a variable whose current value is "Henrietta", the macro expands to:
α{"Peter Pauper --- Henrietta"}
$SS MACRO CALLS
A macro can be called from anywhere in a command line as well as inside
curly brackets on a text line. A value parameter must be a "SAIL" expression (see
{YON EXPRS}), while a literal parameter may take any of three forms
(form 2 is recommended):
$BEGIN narrow 10 indent 0,6
(1) A string enclosed in "..." in which every " inside is represented by "" .
It must appear all on one line.
(2) A string enclosed in |...| in which no | appears. It may span several
command lines.
(3) A string not beginning with " or | and containing no comma or right
parenthesis. It must appear all on one line. Leading spaces are ignored.
$END
$break
Thus, all the folowing are equivalent:
$BEG
PLUG IN ("Peter Pauper", V)
PLUG IN (|Peter Pauper|, V)
PLUG IN ( Peter Pauper, V)
"Peter Pauper --- Henrietta"
$END
$ss OMISSIONS
Any actual parameter may be omitted; its value is then NULL. Furthermore,
if all parameters that follow it are also omitted, all their terminal
commas may be omitted.
In a macro call -- but not in a macro declaration -- the parentheses around
the actual parameter list may be omitted (both -- not just one). However,
care must be taken if this is done. In particular, the comma that follows
each parameter must appear on the same line as the parameter. Also, the
third form of literal parameter may not contain any of the following:
$ins
, ) ] ; α} ⊂ CR
This convention is useful for macros to generate section headings; a typical
call is:
$ins
.SEC SPECIAL FEATURES
which is equivalent to:
$ins
.SEC(|SPECIAL FEATURES|)
and would presumably go to a new page, update the section number, print the
heading centered, and send it to the Table of Contents for inclusion there.
How to do all this will unfold gradually.
$SS RECURSIVE MACROS
If a macro is declared "RECURSIVE MACRO ...", then when its call
occurs in the FALSE part of a conditional, the compiler
processes the actual parameters as usual, but does not expand the macro
body. Instead, the whole call is replaced by NULL.
For macros not declared RECURSIVE, their bodies are expanded
even in the FALSE part of a conditional. This prevents syntactic anomalies,
but attempts at recursion will create infinite looping.
Recursive macro hackers:
If you call a RECURSIVE macro after a conditional statement, an empty
statement must intervene:
$INS
.IF A<0 THEN B ELSE C ; ; RECMAC(...) ;
$sec EXPRESSIONS
$ss DATA TYPE,EXPRS:
PUB has only one data type: ↓_String_↓. A string consists of zero or more
ASCII characters.
≤Strings≥ may participate in ≤arithmetic≥ operations. The string "764" is
automatically converted to the ≤integer≥ 764 for this purpose. The result
of the operation is similarly converted back to a string. Because of
this convention, the data type ↓_Integer_↓ exists for all practical purposes.
$ss VARIABLES
Variables may be declared by the command:
$ins
.VARIABLE A, BETA, C
This would make A,#BETA,#and#C ≤local≥ to the innermost block in which the
declaration occurred. The variables are of course type String.
Any variable that is assigned but not declared is automatically ↓_≤Global≥_↓.
All declared variables are initiallized to ≤NULL≥, the string of length zero.
The name of a variable is an ↓_identifier_↓.
The first character of an identifier should be a letter
The letter may be followed by letters, digits,
_, and !. The identifier is terminated by any other character, including CR.
Before looking up an identifer in its symbol table, PUB changes
all lower case letters to upper case and changes _ to !.
In syntactic descriptions in this manual, ≤<id>≥ will denote any
identifier, and ≤<v>≥ will denote a variable in particular.
$SS AUTOMATICALLY DECLARED VARIABLES
Some variables are automatically declared for you by the compiler, in a
block outside your outermost block. A few of these are read-only -- it
is not possible to assign them a value by an assignment statement.
$BEAK APART IF LINES < 8 THEN NEXT PAGE
→≤CHAR≥\\(read-only) The number of characters so far printed on the current output
line, not counting justification spaces. This is sometimes an overestimate.
→≤LINE≥\\(read-only) Value is zero if the current output column is empty.
Otherwise, the sequential number of the last line output.
→≤COLUMN≥\\(read-only) Value is zero if the current page is empty. Otherwise
the sequential number of the last column in which output went.
→≤CHARS≥\\(read-only) The number of character positions remaining to be filled on
the current output line.
→≤LINES≥\\(read-only) The number of unused lines remaining in the current output column.
→≤COLUMNS≥\\(read-only) The number of unused columns remaining in the current page.
→≤TOPLINE≥\\(read-only) The line number on this page that starts the current area.
(see {YON AREAD}).
→≤FILLING≥\\(read-only) FALSE ("0") if in a NOFILL mode. TRUE if in FILL mode --
"1" if ADJUST, "-1" if NOJUST.
→≤NULL≥\\(read-only) The empty string ("").
→≤TRUE≥\\(read-only) "-1"
→≤FALSE≥\\(read-only) "0"
$ONCE SPREAD←2
→≤SPREAD≥\\The intra-paragraph output line spacing. SPREAD=1 is single
spacing, SPREAD=2 is double spacing, etc. Its initial value is 1 unless otherwise
specified in the (nS) CUSP option.
→≤INDENT1≥\,#≤INDENT2≥,#≤INDENT3≥ Control paragraph indentation
(see {YON INDS}).
→≤LMARG≥\,#≤RMARG≥ The left and right margins (see {YON MARGS}).
→≤DATE≥\\Today's date, in the form October#16,#1848#. Initiallized from the
system DATE UUO just before your manuscript is compiled.
Also available individually are MONTH, DAY, and YEAR. To fully capitalize
the month or date, use the α↑ operator described in {YON SIMPEX} (e.g., α↑MONTH).
→≤TIME≥\\The time your compilation began, in the form 16:47#.
→≤FILE≥\\The first name of your manuscript file. Useful for headings.
→≤PAGE≥\\The current page number, initially NULL. Don't declare this LOCAL!
→≤_SKIP_≥\\(read-only) May be set by extreme substring operators (see SAIL manual, 9-43).
To examine the left and right halves, examine _SKIPL_ and _SKIPR_.
→≤FOOTSEP≥\\Before the first footnote (if any) in each column, a blank line
is usually left.
This is because FOOTSEP is initially NULL. If you assign it another value,
then that string will be printed instead.
$END
$ss SIMPLE EXPRESSIONS,SIMPEX:
Most of the SAIL <string expression> syntax has been implemented. Exceptions:
function designators (but there are macro calls); exponentiation; LDB, ILDB, and LOP;
shifts and masks; LEAP operators.
PUB has three unary operators of its own: "α↑" capitalizes its argument (only
lower case letters and underbar are affected). EVEN and ODD are predicates
which tell whether the low order bit of the last character of a string is
off or on. They are used primarily to distinguish left and right facing
pages:
$ins
.IF ODD PAGE THEN etc.
All the available operators are listed in the table below. If operator op1 is
listed above operator op2 then op1 is performed before op2.
$BEG
(\)
[\]
+ -\ABS\LENGTH\α↑####(this + and - are unary)
*\DIV /\MOD\&
+ -\EQV ≡\XOR ⊗\######(this + and - are binary)
MAX\MIN
EVEN\ODD
> < =\α≤ LEQ\≥ GEQ\≠ NEQ
¬\NOT
∧\AND
∨\OR
$END
The identifiers OR, LEQ, etc. are not ≤reserved words≥ except in context.
(The same holds for all identifiers in the language except command names.)
Both division operators (/, DIV) are equivalent -- they yield the truncated integer.
= and ≠ compare strings character-by-character; <, >, etc. compare
integers algebraically.
If neither TO nor FOR occurs in a ≤substring≥ specification, FOR 1 is assumed.
Note that:
$BEG
7654[α∞] = 4
76 & 54 = 7654
$END
$ss GENERAL EXPRESSIONS
≤Assignment expressions≥ and ≤conditional expressions≥ are allowed. If used
alone to compute text, enclose them in parentheses, otherwise they will
look to the compiler like assignment ↓_statements_↓ or conditional
↓_statements_↓, and the text processor won't scan their values.
In syntactic descriptions, ≤<e>≥ will denote a general expression --
simple, assignment, or conditional, while ≤<se>≥ will denote a strictly simple
expression.
$ss CONSTANTS
PUB recognizes three forms of constants: quoted, decimal, and octal. WARNING: CR
will terminate any form, so don't continue a quoted constant on a new line.
A quoted constant (≤<qc>≥) is a sequence of characters surrounded by quotes ("...").
To include a quote in the represented ≤string≥, write two ≤quotes≥ ("") in the constant.
A ≤decimal≥ constant (≤<dc>≥) is a sequence of decimal digits.
An ≤octal≥ constant (≤<oc>≥) is an apostrophe (') followed by a sequence of
octal digits. The value of the octal number is taken modulo 200↓8 and
converted to a one character ≤ASCII≥ string. The following octal codes are
illegal: '0, '11-'15, '175, '177.
$sec STATEMENTS
$ss STATEMENT TYPES
Syntactically, any command can be a statement
(abbreviated ≤<s>≥ in this manual).
There are two categories of commands: ≤declarative≥ and ≤imperative≥. A ↓_≤declaration≥_↓
is limited in its ≤scope≥ by ≤block structure≥, while an ↓_imperative_↓ isn't.
$SS BLOCK,BLOCKS:
$syn
BEGIN [<qc>] <s> ; ... END [<qc>]
The optional block name [<qc>] should be the same in both places. Mismatches will
be flagged. Missing END's are calamitous to say the least!
Note that declarations don't have to be the first thing in the block. The
scope of a declaration is the remainder of the innermost block in which it occurs.
Both ≤BEGIN≥ and ≤END≥ cause a paragraph break. Neither produces output, not even a blank line.
The semicolons between statements may be omitted as long as no ambiguity is
presented thereby.
$ss COMPOUND STATEMENT or CLUMP
$syn
START [<qc>] <s> ; ... END [<qc>]
Declarations are not local to clumps, and ≤START≥ and ≤END≥ never break. Thus:
$ins
.IF TRUE THEN START FILL ; ADJUST END ;
sets the modes FILL and ADJUST and leaves them set after END. If BEGIN had
been used instead of START, the ≤scope≥ of the modes would have extended
only to END.
$SS ONE PARAGRAPH SCOPE,ONCES:
$syn
ONCE
The command ≤ONCE≥ breaks and begins a local ≤scope≥ which is implicitly terminated
by the end of the next paragraph. There must ↓_not_↓ be an
END provided to match it. If a BEGIN is encountered before a paragraph breaks,
then everything that has been declared in the ONCE's scope is donated to
the scope of the BEGIN's block and the ONCE is forgotten.
Examples:
$BEG
.ONCE FLUSH RIGHT
George
$END CONTINUE
is equivalent to:
$BEG
.BEGIN FLUSH RIGHT
George
.END
$END CONTINUE
and
$BEG
.ONCE FILL
.BEGIN NOJUST
Harry
.END
$END CONTINUE
is equivalent to:
$BEG
.BEGIN FILL NOJUST
Harry
.END
$END
You will find the ONCE construct useful in writing macros and in formatting odd
paragraphs here and there. Note that ONCE is a complete statement, unlike
BEGIN, which introduces a statement that extends to the matching END. Thus,
you can say "IF X THEN ONCE ELSE iα←i+1" but you can't say "IF X THEN BEGIN
ELSE iα←i+1".
$SEC DECLARATIONS
$ss SCOPE
(For the third time:) A declaration is in force until the occurrence of an
overriding declaration or until the end of the innermost block in which
it occurred (see {YON BLOCKS} through {YON ONCES}).
$ss MODE DECLARATIONS,MODED:
Most of these have already been described.
Some mode declarations cause ≤paragraph break≥s and some don't.
The ones that first Break are: FILL, all the NOFILLs, ADJUST, NOJUST, GROUP, and APART.
The ones that don't are: CRBREAK, CRSPACE, COMPACT and RETAIN.
$SS TABS DECLARATION,TABS:
$syn
TABS <e>, ...
The expressions are sorted in algebraic ascending order and duplicates are
eliminated. These then become the tab stops for the α\ control character.
If you tab when the target is already passed, no spaces are inserted,
but justification to the left of the current position in the output
line is inhibited anyway. Tab distances are measured from the left margin.
$ss INDENT DECLARATION, INDS:
$syn
INDENT [<e>] [ ,<e>] [,<e>]
This command can change the values of three parameters that control paragraph
format: ≤INDENT1≥, ≤INDENT2≥, and ≤INDENT3≥. They can also be changed directly by
assignment statements. Every change is local to the current block.
$BEGIN INDENT 20,25,8
INDENT1 and INDENT2 specify indentation from the left margin.
INDENT1 specifies the value of the ↓_crown indentation_↓,
which affects only the first line of output paragraphs.
INDENT2 specifies the value of the ↓_vest indentation_↓, which
affects non-first lines in FILL mode.
In NOFILL, SUPERIMPOSE,
and JUSTJUST modes, INDENT1 is observed, and INDENT2 is ignored.
Old PUB users note: this is a change from previous conventions.
INDENT3 specifies indentation from the right margin in FILL mode.
It is ignored in NOFILL modes, and in text affected by the control
characters "α→", "α←", and "α∞".
Lines in VERBATIM, FLUSH LEFT, CENTER, and FLUSH RIGHT modes are
never indented.
If any argument is omitted, the corresponding parameter remains unchanged.
$END
$ss PREFACE DECLARATION
$syn
PREFACE <e>
$PREFACE 3
PREFACE N will cause every output paragraph to be preceded by an implicit
SKIP N. There are actually two Preface numbers maintained -- one for
FILL mode and one for NOFILL modes. The one you change by this command
depends on the current mode.
Initially, the FILL Preface is 1 and the NOFILL Preface is 0.
$PREFACE 1
You may want to vary the Prefaces according to SPREAD, e.g., PREFACE 1+SPREAD .
$ss DOUBLE SPACING
$syn
$begin group
≤SINGLE SPACE≥
≤DOUBLE SPACE≥
≤TRIPLE SPACE≥
$END
These are standard macros that set ≤SPREAD≥ to 1, 2, and 3, respectively. At
the end of the current block, the old value is restored. SPREAD controls the
spacing between lines within a paragraph.
$ss AREA DECLARATION,AREAD:
$syn
$BEGIN GROUP
[TEXT|TITLE] AREA <id> [LINE[s] <e> [TO <e>]] [CHAR[S] <e> [TO <e>]]
\[IN <e> COLUMNS <e> WIDE|APART]
$END
Each page is divided into ↓_Areas_↓ into which the compiler will place output
text. The areas ≤HEADING≥, ≤TEXT≥, and ≤FOOTING≥ are ↓_pre-declared_↓ for you as follows:
$BEG
.AREA TEXT LINES 4 TO 51 ;
.TITLE AREA HEADING LINES 1 TO 3 ;
.TITLE AREA FOOTING LINE 53 ;
$END
$IF LINES < 23 THEN NEXT PAGE ELSE SKIP 1
$BEGIN indent 0,0
$AREA LISTING LINES TOPLINE+LINE TO TOPLINE+LINE+24 IN 2 COLUMNS 7 APART
$PLACE LISTING
Each area is a rectangle that must lie within the bounds set by the last PAGE
FRAME Statement (see {YON PGFRM}).
If the CHARS clause of the AREA declaration should be omitted
(as it is in the predeclared areas), then the full width of the Page Frame is assumed.
Similarly, if the LINES clause should be omitted, full page height is assumed.
An area is assumed to be a ≤TEXT AREA≥ unless "≤TITLE AREA≥" is stated explicitly.
The only difference between a TEXT AREA and a TITLE AREA is the action taken
when so many lines are written in it that it overflows. In the case of a TEXT
AREA overflow, all areas are "closed", the whole page is written out, and a new
page is begun. In the case of a TITLE AREA overflow, an error message is issued.
An area has one column unless an IN..≤COLUMNS≥ clause is included, e.g.,
$BEG
.AREA LISTING LINES 30 TO
. 50 IN 2 COLUMNS 7 APART
$END
Either how WIDE each column is or how far APART they are can be specified.
Associated with each area are a left and right margin, located initially
at the left and right edges of each column.
How they can be moved inward and back out is explained in {YON MARGS}.
$END
$GROUP SKIP 25
The bottom line of a TEXT AREA is not used except to print the last line of a
paragraph. This convention prevents the appearance of "≤widows≥" at the top
of a page.
$Ss MARGIN CONTROL,MARGS:
$syn
NARROW <se> [ ,<e>] <paragraphs and statements> WIDEN
≤NARROW≥ and ≤WIDEN≥ cause paragraph breaks. NARROW L,R moves the left and
right margins of the current PLACE area inward L and R, respectively.
Their initial positions are determined by the AREA declaration.
L and R may be negative. If either is
omitted, it is assumed 0. The matching WIDEN restores the margins to their
former positions.
Alternatively, you can have:
$ins
WIDEN <se> [ ,<e>] <paragraphs and statements> NARROW
which moves the margins outward. Both kinds can nest.
These commands change the automatically declared variables LMARG and RMARG
(the Left and Right Margins). They can also be changed directly by
assignment statements; such changes are local to the current block and
to the current NARROW-WIDEN nest of the current PLACE area.
Upon exit from a block, if the margin positions are different than they
were at the beginning, then they are restored and
instead of the usual Break, END causes
a ≤CONTINUE≥ (See {YON CONTI}),
which treats the next line as a vest instead of a crown line.
$BEGIN GROUP
Every paragraph is output in the following format:
$BEG turn off "←→↑↓-." ;
| ---------------------------------------- |
| | | | |
| | ( P blank lines) | | |
← A-1 →| | | | |
| |←- I1 -→The crown line of the paragraph.| | |
| |←----- I2 ----→a vest line .............|← I3 →| |
|← L →| another vest line .......| |← R →|
| | the hem line. | | |
| ---------------------------------------- |
↑ ↑ ↑ ↑
A Left-margin Right-margin B
$END
$END CONTINUE
The format suggested by the diagram above may be achieved by the following declarations:
$BEG
.AREA TEXT CHARS A TO B ;
.NARROW L, R ;
.FILL ; PREFACE P ; INDENT I1, I2, I3 ;
$END
The automatically declared variable ≤CHAR≥ and all ≤tab≥ stops count characters
from the left margin; they may at times be negative. It is possible to
produce ≤output past the right margin≥ by setting tab stops out there.
$ss PLACE DECLARATION
$syn
PLACE <area id>
This breaks and switches output to the named area. This may be done many
times on the same page; output to each area always picks up where it left off.
If a column of the current Place Area overflows, output
continues at the top of the next column. When the last column overflows,
either a new page is begun (if a TEXT AREA overflowed) or an error message is
given (if a TITLE AREA overfowed).
$ss TEMPORARY AREAS
This section is complicated. Only read it if you need to create
temporary areas within a page.
To do this, you need to know where you're up to on the page so far.
If there's not enough room for the new area, you will want to go to a new
page. Then a temporary area (local to a block) should be declared, and
text placed in it. Finally, you may need to find out where you're up
to on the page again before you exit that block, skip over the temporary area,
and resume regular output.
A more convenient way to handle this may be available in a future version of PUB in the
form of a BOX FRAME declaration. In the meantime, you should be able to
get by as follows.
To determine the top line on the whole page that the current PLACE
area uses, look at TOPLINE. Within that area, lines are numbered starting
from 1 -- but if TOPLINE is 6 that means "line 1" of the area is really the 6'th line
on the page. We can distinguish P-lines (numbered relative to the whole
page) from A-lines (numbered local to the area); A-line 1 might be P-line 6.
To determine the column number and A-line number of the last line output
in this area, look at COLUMN and LINE. To determine how many empty columns
remain in this area, look at COLUMNS; for how many empty lines remain
in this column, look at LINES. Note that LINE+LINES can be less than
the full height of the area, because a few lines at the bottom may be
occupied by footnotes.
To declare a two-column area 10 lines high for a table starting just below the last output
line, write:
$BEG
.IF LINES < 10 THEN NEXT PAGE ;
.BEGIN
.AREA AXE LINES TOPLINE+LINE TO TOPLINE+LINE+9 IN 2 COLUMNS 5 APART
.PLACE AXE
\<table text>
.END
.GROUP SKIP 10
$END CONTINUE
Adding TOPLINE in the AREA declaration is necessary because it expects P-line
numbers.
$ss COUNTER DECLARATION,COUNTERD:
$syn BEGIN GROUP
≤COUNT≥ <id> [INLINE] [FROM <e>] [TO <e>] [BY <e>] [IN <counter id>]
\[PRINTING <e>|<template>]
$END
This is PUB's excuse for a FOR statement. The user can declare certain
identifiers to be ↓_counters_↓, and arrange them in hierarchies. A counter is anything
you want numbered sequentially. Typical counters
are ≤SECTION≥, ≤APPENDIX≥, ≤SUBSECTION≥, ≤PAGE≥,
≤FOOTNOTE≥, ≤EQUATION≥, ≤TABLE≥, ≤FIGURE≥,
NOTE, and ≤REFERENCE≥. A common ≤hierarchy≥ is:
$BEG
\\#####SECTION
\\####α/#######α\
\\SUBSECTION##PAGE
\\#############|
\\##########FOOTNOTE
$END
The declarations for this hierarchy might be:
$BEG
.COUNT SECTION FROM 1 TO 9
.COUNT SUBSECTION FROM 1 TO 99 IN SECTION
.COUNT PAGE FROM 1 TO 99 IN SECTION
.COUNT FOOTNOTE INLINE FROM 1 TO 9 IN PAGE
$END
The "IN" clause specifies the hierarchial parent counter; it must have been
previously declared.
The range of each counter
is specified by the FROM, TO, and BY clauses; if omitted, FROM 1, TO 18,
and BY 1 are assumed. The counter need not ever attain the TO-value; it is just
an upper limit used to determine the
maximum number of characters needed to print the counter in case it is
referred to in a ≤Forward Cross-Reference≥ (see {YON XREF}).
The INLINE option suppresses a BREAK which is otherwise automatically
generated before each stepping of the counter.
The PRINTING clause is explained in {YON NEXTS}.
$sec IMPERATIVES
The commands in this section are non-declarative. That means that their
scope is not limited by ≤block structure≥.
an occasional exception to this rule is the ≤assignment statement≥;
when the assigned variable is ≤SPREAD≥, ≤LMARG≥, ≤RMARG≥, ≤INDENT1≥, ≤INDENT2≥,
or ≤INDENT3≥, then the change is local to the current block.
$ss ASSIGNMENT STATEMENT
$syn
<v> α← <e>
Example:
$INS
.SPREAD α← T α← r - 4 ;
Assignment statements don't break.
$ss CONDITIONAL STATEMENT
$syn
≤IF≥ <e> ≤THEN≥ <s> ≤ELSE≥ <s>
Example:
$BEG
.IF ODD PAGE OR LINES < 10 THEN START
this text line
.END ELSE START
that text line
.END
$END
"IF", "THEN", and "ELSE" don't break.
$SS NEXT COUNTER VALUE STATEMENT,NEXTS:
$syn
NEXT <counter id>
This breaks (unless ≤INLINE≥ appeared in the designated counter's ≤COUNT≥ declaration),
and the counter is stepped to its next value. The first
time it is called, the counter's value is initiallized.
Every COUNT declaration automatically declares two variables with special
properties, and initiallizes them to NULL. The first variable has the
same name as the <counter id>, e.g., "SUBSECTION", and its value is always
the decimal integer value of the counter. The
other variable's name is constructed by appending an "≤!≥" to the <counter id>,
e.g., "SUBSECTION!". The two variables are called the counting or "≤C-value≥"
and the printing or "≤P-value≥", respectively.
The precise effect of the statement "NEXT U" in terms of these variables is
as follows.
(1) If U=NULL, then U is set to the ≤FROM≥ value of the COUNT
declaration; otherwise, U is incremented by the ≤BY≥ value of the COUNT
declaration.
(2) The P-value is computed under control of the ≤PRINTING≥
clause of the COUNT declaration (just how will be explained shortly).
In addition, the P-value is assigned to the variable "≤!≥" as a convenient abbreviation.
(3) If the counter has hierarchically subordinate counters, all their C-values and
P-values are set to NULL; thus, when you say NEXT SECTION, SECTION
becomes a new number while SUBSECTION, PAGE, and FOOTNOTE become NULL
(assuming the hierarchy of the recent example).
Exception: If "PAGE" was one of the subordinate counters, after it is cleared it is
immediately initialized.
The computation of the P-value depends on the ≤PRINTING≥ clause of the COUNT
declaration. There are three cases.
$BEGIN INDENT 0,10 TABS 11
↓_Case One_↓\The PRINTING clause is omitted. P-value is the same as the
C-value.
↓_Case Two_↓\PRINTING <template>. After each C-value is computed, the
expression inside the template is evaluated, and the result is the
P-value. Thus, the template should contain an expression which involves
the C-value. Examples:
$BEG
.COUNT FOOTNOTE TO 9 IN PAGE PRINTING ⊂"*********"[1 TO FOOTNOTE]⊃ ;
$END CONTINUE
When FOOTNOTE=1, this sets FOOTNOTE!=*; when FOOTNOTE=5, this sets FOOTNOTE!=*****.
$BEG
.COUNT SUBSECTION IN SECTION PRINTING ⊂SECTION! & "." & SUBSECTION⊃ ;
$END CONTINUE
When SECTION!=4 and SUBSECTION is counted to 7, SUBSECTION! becomes 4.7 .
↓_Case Three_↓\PRINTING <e>. The expression is evaluated only once, at
declaration time, and its value serves as a pattern for conversion of
the C-value to the P-value.
For example, the pattern "(i)" will produce P-values such as (iv) and (xlii),
and the pattern "!-A" will produce P-values such as 6α-A and 33α-L.
The pattern should evaluate to a string of the
form:
$ins
<prefix> [ ! <middle> ] <format> <suffix>
$continue
where <prefix>, <middle>, and <suffix> may be empty, and <format> must be
1, a, A, i, or I. This is roughly equivalent to the template:
$INS
⊂<prefix>& ! &<middle>& CONVERT(<counter id>,<format>) &<suffix>⊃
$continue
Here's what happens. The P-value becomes this pattern
after substituting the parent counter's P-value for "!" (if present) and
after converting the C-value to the specified format and substituting it
for <format>. Before explaining formats, let's give a simple example:
$BEG
.COUNT SUBSECTION IN SECTION PRINTING "!.1" ;
$END CONTINUE
Here, <prefix> and <suffix> are empty and <middle> is ".". Format "1"
is no-conversion, so the C-value is substituted unchanged for the "1".
The P-value of SECTION is substituted for the "!". Say SECTION! is 6
and SUBSECTION is stepped to 4; then SUBSECTION! becomes 6.4 .
$GROUP CONTINUE
The various <format> conversions are:
$BEG
1\No conversion
I\Upper case ≤Roman≥, i.e., 59 α→ LIX
i\Lower case Roman
A\Capital letters A,...Z,AA,BB,...ZZ,AAA,...
a\Little letters
$END
$APART
$END
$SS NEXT PAGE STATEMENT
This variety of Next Statement has special properties. Before
stepping the PAGE counter, it "closes" and outputs all the areas on
the current page and sets up a fresh page frame.
Conversely, when a page is closed due to text area overflow or "SKIP TO
COLUMN 1", etc., the page counter is automatically stepped before the
new page is opened, as if the command NEXT PAGE had been given.
$ss HEADINGS AND FOOTINGS,TITLES:
As soon as the first line is ready to be placed in a page, the page is
"opened". There are fancy ways you can create fancy headings and footings
at that or at other times (see {YON HEDRESP}). For simple cases, the following command
(which is actually a call to a built-in macro) is provided.
$syn
.EVEN|ODD|EVERY HEADING|FOOTING ( <text>, <text>, <text> )
On left-facing (EVEN), on right-facing (ODD), or on all pages (EVERY); on the top
line (HEADING) or the bottom line (FOOTING);
the three <text>s will be printed at the left edge,
the center, and the right edge of the page, respectively. A <text> may not
contain quote ("). Example:
$INS
.ODD HEADING(α{DATE}, MACHINES THAT WONDER, α{SUBSECTION!})
This would cause to print on the top line of every right-facing page something
like:
$ins
July 14, 1789←MACHINES THAT WONDER→VII.iii
$ss SECTIONING
The correct way to start every new section on a new page is:
$ins
.NEXT PAGE ; NEXT SECTION ;
If the order of these were reversed and if SECTION were the parent of PAGE,
then NEXT SECTION would change PAGE's value before the old page got written out.
$ss COMMAND CHARACTER STATEMENT
$syn
COMMAND CHARACTER <qc>|<v> ;
The parameter must evaluate to a single character string.
That character subsequently assumes the function of ≤dot in column 1≥.
Since this command
is not a declaration, its scope is global; i.e, it is not affected by block
nesting. Don't omit the semicolon!
$SS PORTION DEMARCATION,PORTIONS:
$syn
PORTION <id>
The manuscript may be (ought to be) divided into ↓_Portions_↓, such as
≤TITLEPAGE≥, ≤CONTENTS≥, THESIS, ≤APPENDICES≥, NOTES, ≤INDEX≥, and ≤BIBLIOGRAPHY≥.
Precede each portion by a Portion Demarcation, e.g.,
$ins
.PORTION NOTES
The compiler will assure that each portion starts on a fresh page and ends
with a paragraph break.
In general, the order of appearance of the portions in the manuscript
becomes their order of appearance in the document. However, this is not
always convenient. For example, the entries for PORTION CONTENTS are
usually generated during the processing of the other portions (see {YON
$SENDS}); therefore, ↓_PORTION CONTENTS must appear at the end of the
manuscript_↓. To show where you would like its output to be inserted in the
document, use the statement:
$ins
.≤INSERT≥ <id>, ...
which is sort of a "forward portion demarcation". Example:
$BEG
.PORTION TITLEPAGE
\...
.INSERT CONTENTS
. COMMENT This is where the table of contents should be printed;
.PORTION THESIS
.COUNT PAGE ; COMMENT Before NEXT SECTION starts a new page;
.NEXT SECTION
\...
.PORTION INDEX
\...
.COUNT PAGE PRINTING "i"; COMMENT Before PORTION starts new page;
.PORTION CONTENTS
. COMMENT This is where the table of contents is defined ;
\...
$END
$SS SEND STATEMENT,SENDS:
$syn
SEND <portion id> [;] <template>
With every portion is associated a file called its ↓_generated file_↓.
A ≤generated file≥ is in ∪manuscript format. The idea is that you can avoid
manual preparation of certain portions of your manuscript (such as the
≤table of contents≥ and the ≤index≥) by making PUB prepare them mechanically.
The generated file of a portion
may remain empty, or may be written on during the processing of portions
that appear earlier in the manuscript. For example, the generated files for
PORTION ≤CONTENTS≥ and PORTION ≤INDEX≥ are usually generated during the processing
of earlier portions.
The SEND statement writes a template onto the end of the generated file for
the named portion. The portion must appear later in the manuscript. Before
sending the template, the compiler substitutes for every occurrence of:
$ins
α{ <v> α}
the (unquoted) value of the variable <v>.
Thus, if S=6 and PAGE=26, then the statement:
$BEG
.SEND CONTENTS ⊂
Section α{Sα} -- Findings α∞.α→ α{PAGEα}
.⊃ ;
$END CONTINUE
would send the following data to the file associated with PORTION CONTENTS (CRLF
shown here for clarity):
$BEG
<CRLF>
Section 6 -- Findings α∞.α→ 26<CRLF>
.
$END
If a similar SEND were performed at the beginning of every section and subsection
of the manuscript, then by the time the compiler reached
PORTION CONTENTS, its generated file would be in perfect manuscript format, e.g.:
$BEG
Section 1 -- Introduction α∞.α→ 1
.
Section 2 -- Remarks α∞.α→ 6
.
\(etcetera)
Section 6 -- Extraneous Factors α∞.α→ 26
.
\(etcetera)
Section 413 -- Conclusions α∞.α→ 864
.
$END CONTINUE
The empty command lines are of course harmless; their inclusion was caused by
the method of conforming with one of the rules of writing templates: a template
must end on a command line. Of course, a template alternatively could end
with a text line terminated by "α{".
The subtleties of generated files are discussed in the Appendices to this
manual. If you would rather postpone becoming an expert on the technique,
you can still obtain a table of contents and index by the use of someone
else's macros. These macros (≤STANDARD FRONT≥ and ≤STANDARD BACK≥) are
stored in file ≤PUBMAC.DFS≥[1,3] and described in file ≤PUBMAC.TES≥[UP,DOC].
$ss RECEIVE STATEMENT
$syn
RECEIVE [<qc>|<v>]
This statement substitutes the ≤generated file≥ of the current portion for
the statement and causes the compiler to compile it.
Thus, PORTION CONTENTS typically consists of a few mode setting commands, a
title, and then the statement "RECEIVE".
If the optional parameter is present, it should evaluate to a string of one or two
characters, say "L" or "LR". The presence of the parameter causes the
generated file to be ≤alphabetize≥d before it is compiled. Entries in the
file should be in the form:
$ins
<0 or more characters> L <Key> [R <0 or more characters>]
PUB will alphabetize the entries by the <Key>s using the ≤ASCII≥ ≤collating sequence≥,
except lower case letters and "_" are ranked with the corresponding upper case
letters and "!".
Then it will read the alphabetized file, including the L and R characters.
WARNING: The characters L and R must be chosen carefully. They may not occur in the
generated file in any role except as key delimiters. Furthermore, the characters
"α[", "α]", "α@" may not be used. It is legal for L and R to be the same character.
If your index is very large, PUB may exhaust SAIL string space trying to alphabetize
it. The error message "≤STRING SPACE EXHAUSTED≥" will be typed out. Unfortunately,
the only way to get more string space is to REEenter the program and go through
the ALLOC ritual (see SAIL manual 14-22). The original allocation is presently
4000 words; try 7000 or 10000.
To generate a simple ≤index≥, use SEND statements such as:
$BEG
.SEND INDEX ; ⊂
αβKeyword α∞.α→ α{PAGEα}
.⊃ ;
$END CONTINUE
and the RECEIVE statement:
$ins
.RECEIVE "αβα∞"
The file generated will be quite funny-looking, but will result in the
document:
$BEG
...
Keyshmurd ......................... 9
Keyword .......................... 15
...
$END CONTINUE
Rather than all those hideous dots, it is suggested that the number immediately
follow or precede the word.
To learn how to
create two-level and KWIC indexes, see {YAP INDEXIX}.
$ss REQUIRE STATEMENT,REQR:
$syn
REQUIRE <qc>|<v> SOURCE_FILE
The parameter must evaluate to a file name, e.g., "BRAIN.BAZ[H,AHA]". The
file must be in manuscript format. It will be substituted
for the REQUIRE statement and compiled. If the last line of the file
is a text line, PUB will still be scanning for text when it resumes the
original file, so don't put a semicolon after the REQUIRE statement -- put a CR.
REQUIREd files may REQUIRE other files. You will run out of ≤channels≥ if
the number of open SOURCE_FILEs, generated files (extension ".PUG") and
pass one output files (extension ".PUI") exceeds 15.
$ss SKIP STATEMENTS,SKIPS:
$SYN BEGIN
[GROUP] SKIP [<se>]
SKIP TO LINE <e>
SKIP TO COLUMN <e>
$END
$group SKIP 8
≤SKIP N≥ breaks and leaves N blank lines in the document. If N is omitted, SKIP 1
is assumed. Note that N must be a simple expression -- no assignment or
conditional expression is allowed unless it is parenthesized.
Blank lines
that would appear at the top of any column are automatically suppressed; if
you want to force them to appear (say, to leave space for a drawing), use
≤GROUP SKIP≥.
If you are going to run off the same document with different values of SPREAD (i.e.,
sometimes single space and sometimes double space), you should write all your
KIP statements with this factor taken into account, e.g., SKIP#2*SPREAD-1 .
≤SKIP TO LINE N≥ outputs blank lines up to but not including the N'th
line (A-line) in the current column of output text, unless the N'th line has already
been passed, in which case it goes to the N'th line in the next column. The
most common use of this statement is SKIP TO LINE 1, which assures you are
at the top of a clean column.
≤SKIP TO COLUMN N≥ outputs blank lines until it reaches the top of the N'th
column of this or the next page. If the compiler is already at the top
of the N'th column, this statement does nothing. The most common use is
SKIP TO COLUMN 1, which goes to a new page unless a new page has just
been begun. (To go to a new page regardless, use "NEXT PAGE" -- See {YON NEXTS}).
$ss PAGE FRAME STATEMENT,PGFRM:
$syn
PAGE FRAME <e> HIGH <e> WIDE
This statement causes a break, goes to a new page, and sets up its size
as specified (number of lines, number of characters). No output can
appear outside the bounds set by this statement. Area declarations normally follow it.
$SS BREAK STATEMENT
$SYN
BREAK
If a paragraph has been started, BREAK terminates it. Breaks
are implicitly caused by many other commands and conditions.
$ss CONTINUE STATEMENT,CONTI:
$syn
CONTINUE
Sometimes you would like to insert an indented quotation or equation in the
middle of a paragraph of prose. After the quotation, a paragraph break is
necessary to terminate it.
$BEGIN SPREAD ← 1 NARROW 5,5 PREFACE 0
Unfortunately, the break also causes the next
output line to be treated as a crown line (in FILL mode). If you would
rather continue the interrupted paragraph than start a new one, use the
command CONTINUE.
$END CONTINUE
It breaks, but causes the next paragraph to have no
crown, as long as no regular breaks intervene.
$SS DEVICE STATEMENT,DEV:
$syn
DEVICE LPT|MIC|TTY
This statement is equivalent to setting the /L, /M, or /T switch when starting
up PUB. It has no effect on Pass One output. However, Pass Two reacts to
the switch setting as follows.
≤DEVICE MIC≥ makes the document file be in ≤FR-80≥ command format.
Pass Two will output two temporary files with extension ".RPG" and automatically run
a program called "TXTF80", written by Russ Taylor, which generates the
document file. Simply copy this
file to a tape and bring it to the FR-80 operator at Lockheed.
≤DEVICE LPT≥ and ≤DEVICE TTY≥ produce identical output unless the page frame
is higher than 53 lines. In that case, DEVICE LPT uses strange control
characters instead of line feeds to inhibit page-ejection. DEVICE TTY
assures that only line feeds are issued.
Files produced under DEVICE TTY can be ≤edit≥ed with TECO. Hardly
any document file can be edited with SOS or TVEDIT, which don't like
CR's without LF's
(used for underlining and superimposing).
$SS UNIMPLEMENTED STATEMENTS
The following commands have not been implemented, but ought to be, so their
names are reserved words:
$BEG
≤CASE≥ statement -- SAIL-style
≤ALIGN≥ statement -- it would align output to side-by-side areas
≤PACK≥ statement -- it would align the bottoms of parallel columns
≤BOX FRAME STATEMENT≥ -- to insert a table in a corner of the page
≤LOCK≥ statement -- to protect lines from being moved by a BOX FRAME
≤SHOW≥ statement -- to output to the console during compilation
≤NOPRINT≥ mode -- would suppress output
≤PRINT≥ mode -- would renew output
$END
≤LDX≥ output will soon be available. This will require a few new commands
and automatically declared variables, probably the following:
$BEG
≤DEVICE LDX≥
≤FONT≥ <font-name> ON <file-name> -- would declare a font
≤RASTER≥ <e> UNITS PER INCH -- to specify raster density
≤BELOW≥,≤ABOVE≥,≤ONLEFT≥,≤ONRIGHT≥ -- like LINES,LINE,CHAR,CHARS
≤CHARACTER≥ <name> <font-name> <coordinates> -- define character
$END
$sec COMMENTS
There are two ways to get comments into a command line -- not in the
middle of an identifier or constant, however.
$syn
COMMENT anything but semicolon ;
This one is probably familiar. The other one is:
$ins
<< anything but two greater-than-signs in a row >>
Comments may extend over several command lines. If you leave out the
terminator, you'll lose everything up to the next text line.
Comments have no effect on the document. Why would you want them?
Maybe you could write English comments on a French manuscript to help you
find your way around. Or maybe you've got complicated macros that
need explanation. Or you left out a bunch of text and want to
leave a reminder in the manuscript. Don't ask me why -- I just implemented them.
To get a comment into a text line, use curly brackets around a regular
comment α{<< Like this >>}. Continuation lines must be command lines.
$sec LABELS AND CROSS-REFERENCES
$SS CROSS-REFERENCES,XREF:
A cross-reference is like computed text in that it causes
characters to be processed by the text scanner, and in that it
normally appears between curly brackets in the midst of a text line.
First there will be an example, and then an explanation.
$ins
.α.α. invented by Owsley (See α{"Page!" PURE}) α.α.α.
This might produce output such as:
$ins
.α.α. invented by Owsley (See Page 3-7) α.α.α.
The identifier PURE is called a ↓_label_↓ and must be defined once and
only once in the manuscript, either before or after the cross-reference.
Every label has a value, much like a variable, but the value is assigned
only once, at the place the label is defined.
Several cross-reference statements may reference the same label.
Labels willbe explained further in {YON LABELS}.
There is a major problem in handling ≤forward-references≥ in a
text-justifier. The justifier must know how many characters there
will be in the value before it can decide where to break off the
output line and how many spaces to insert during ≤justification≥. PUB
solves this problem by two slightly awkward hacks. One hack is that
you must state or imply an upper limit on the number of characters,
so it can leave enough room for it and not break off the line too
soon. The other hack is that PUB has two passes. In the second pass,
the actual values are substituted, and only then are
lines justified.
To "state or imply" the upper limit, you have a choice of three forms
of cross-reference.
$SKIP
$ins
Form 1: ↓_[_↓ <e> ↓_]_↓ <label id>
$CONTINUE
Those are really square brackets!!!! Write them in the manuscript, really!
The expression evaluates to a number which is the maximum number of characters, and the
value printed is the value of the label <label id>. If this is a backward
reference (unless to the current page), the number is ignored, so you can say just:
α{[]#<label id>}.
You can't just say the label name.
$SKIP
$ins
Form 2: <counter id>[!] <label id>
$CONTINUE
Those square brackets mean the "!" is optional -- don't write them in
the manuscript! This form means that the value of the label will be
the C-value (if there is no "!") or P-value (if there is an "!") of the counter
<counter id>. PUB can compute the upper limit at declaration time by
looking at the TO clause of the counter's COUNT declaration and at the
≤PRINTING≥ clause, so you don't have to state it. In case the PRINTING
clause used a template, the upper limit is determined by a not quite
foolproof heuristic: suitably large numbers are substituted temporarily
for the C-value of the counter, for both values of its parent, and for !, and
the expression is evaluated.
$SKIP
$ins
Form 3: "<counter id>[!]" <label id>
$CONTINUE
This is identical to form 2, except before sending the value of the label to
the text scanner, it sends the string (without the "!") and a space. Thus, the following are
exactly equivalent:
$BEG
.α.α. See Section α{Section! X} α.α.α.
.α.α. See α{"Section!" X} α.α.α.
$END
The macro used for cross-references in this manual was:
$INS
.MACRO YON(LBL) ⊂ "Section " ; SUBSECTION! LBL ⊃
which was called like this:
$INS
...lots of useless words (See α{yon someplace}). Lots more ......
$ss LABELS,LABELS:
The syntax of <label#definition> and <label#definer> are defined (::=) as:
$syn
$BEGIN GROUP
<label definition> ::= <label id> : <label definer>
<label definer> ::= [NEXT] <counter id>[!] | <e> | <text line>
$END
Here is an example of each kind of <label definer>:
$BEG
.INTRO: NEXT SECTION
.LAPLACE: IF ODD PAGE THEN PAGE ELSE PAGE+1
.EXPLANATION:
This is the line that is labelled by the label "EXPLANATION".
$END
The first kind of definer makes the value of the label be the current
C-value (if there is no "!") or P-value (if there is an "!") of the named counter.
If NEXT is present, the counter is stepped
before the assignment is made.
The second kind makes the value of the label be the value of the
expression. The third kind makes it be the value of PAGE! for the page that
the <text line> begins on.
The first and third kinds of definer both cause a consistency check between all
forward-references to this label that mention a counter name and the counter named here.
The second kind does not cause a consistency check.
CAUTION: There is no consistency check on backward-references. There is no check
when a cross-reference specifies a P-value (or C-value) that the label definition
also specifies a P-value (or C-value). So if the output is incorrect, check
for such inconsistencies yourself.
A label must always be on a command line, or inside curly brackets on
a text line.
If the /D switch was used to obtain debugging information, then
the label will be printed on the right side of the document.
There is a slight ambiguity if your <label#definer> involves PAGE
(or PAGE!). If you use the first or third kind of definer, the
evaluation is deferred until the next text line is output, i.e., until
the next paragraph break or overflowed FILL line. Thus, you may think
of a PAGE label as labelling the following text line; even if a new
page is begun before that line is output, the label value will be
the page on which that line appears. On the other hand, if you use
the second kind of definer (i.e., an expression involving PAGE or PAGE!), the
value used will be the current one at the time of evaluation --
even if the following text line doesn't get output until the next
page.
Note that L:NEXT PAGE will go to a new page and then assign L a value
when the first line is output to that page. If the page is blank,
the assignment is deferred another page. All this kludgery is to
insure that if you say: See α{"Page" X} there will really be something
to see! Be sure to position the label just ↓_before_↓ the text line
you want them to see.
$SEC RESPONSES
$SS TEXT RESPONSES,TEXTRESP:
A Text Response enables you to detect certain conditions in the text, and
to call macro-like subroutines without using α{...}. Presently, four
conditions can be responded to:
$BEG
(1) Page Mark or Form Feed
(2) Blank Text Line
(3) Indented Text Line
(4) Presence of a one-to-five character signal
$END
$SKIP
$SYN
AT <condition> [;] <template>
When the condition is detected, the characters causing it are replaced by:
$INS
α{ <template> }
which is immediately executed.
To dis-declare a response exit the block in which it was declared,
or use a null template:
$INS
AT <condition> [;] ⊂⊃
The various <condition>s available are as follows:
↓_AT ≤PAGEMARK≥_↓ responds to an SOS page mark or a TECO <CR#LF#FF>. A typical use is:
$INS
.≤AT PAGEMARK≥ ⊂SKIP TO COLUMN 1⊃
↓_≤AT NULL≥_↓ responds to a blank text line. There is a predeclared response for this:
$INS
.AT NULL ⊂IF ≤FILLING≥ THEN BREAK ELSE SKIP 1⊃
This is the only reason that blank lines break in FILL mode. You can redeclare
it to treat them otherwise. If you want them ignored, write:
$INS
.AT NULL ⊂IF NOT FILLING THEN SKIP 1⊃
↓_≤AT N≥_↓, where N is a positive integer N, responds to each text line
indented exactly N spaces. For example, the standard macro TABBREAK declares:
$INS
.AT 8 ⊂IF FILLING THEN BREAK ELSE "########"⊃
↓_≤AT S≥_↓, where S is a string beginning with a non-alphanumeric character,
responds to the occurrence of that string (up to 5 characters long)
appearing uninterrupted in a text line. This one <condition> can be followed
by a formal parameter list of up to five arguments, e.g.:
$INS
.AT "%%" A "$" B "%" C "$" ⊂ SEND INDEX ⊂ }A B-Cα{BREAK ⊃ ⊃
Each parameter name is followed by a string containing a single character called its
↓_delimiter_↓. When the signal (in the example, %%) is spotted in a text line, the
compiler continues to scan for actual parameters, terminating each scan
at the appropriate delimiter. An actual parameter may span several text
lines, but each ≤carriage-return≥ is converted to a space if this happens.
No parameters may be omitted. None are evaluated -- they are all literal.
$SS TRANSITION RESPONSES,HEDRESP:
A transition response permits the specification of an action to be
taken at the beginning or end of any counter or at the opening or closing
of any area.
$SYN
≤BEFORE≥|≤AFTER≥ <counter id>|<area id> [;] <template>
Here is how this response fits into the NEXT <counter> algorithm. To execute
NEXT#SECTION, PUB performs six steps:
$BEG
1) If SECTION≠NULL then do AFTER SECTION response (if any)
2) Step SECTION using FROM and BY values
3) Compute SECTION! using PRINTING clause, and assign it to !
4) Do BEFORE SECTION response (if any)
5) For each sub-counter of SECTION, and each of their sub-counters:
\a) If C-value≠NULL: AFTER sub-counter response (if any)
\b) Clear sub-counter C-value and P-value to NULL
\c) If it is PAGE, initialliize PAGE and PAGE!
6) Re-assign SECTION! to ! (steps 4 and 5 may have changed it)
$END
The END of the block in which any counter is declared (except PAGE) also
causes Step 1 to occur.
The most useful transition responses are ≤BEFORE PAGE≥ and AFTER PAGE. The
BEFORE PAGE template is executed not immediately after NEXT PAGE is
executed, but a little later, when the first line of output is ready to
be put on the new page. BEFORE <area id> responses are similarly deferred
until the first output is ready for the named area. The AFTER PAGE template
is executed just before the page is written out -- it had better not place
into a text area that is already full!
One transition response is pre-declared for you:
$INS
BEFORE PAGE ⊂ STANDARD TITLES ⊃
≤STANDARD TITLES≥ is a pre-declared macro that prints the headings and footings
set up by ≤EVERY HEADING≥ and its friends. You can of course redeclare this
response.
Every transition response template is automatically a block. It is
surrounded by BEGIN#!?@3 ... END#!?@3 or something of that sort
(which you will occasionally spot in error messages). It is usually
necessary to declare all the mode settings and formats you want to be in
force inside the <template>. Consider the case of BEFORE PAGE. At the
time that a page happens to overflow, it is entirely possible that the compiler
is in the midst of a FILL block with INDENT 10,20, all control characters
off, and the NOFILL PREFACE set to 2. However, the headings and footings
should be processed in NOFILL mode with preface 0, no indentation, and
several control characters activated. You might declare:
$BEG TURN OFF "{", "←", "→"
.BEFORE PAGE ⊂ NOFILL ; INDENT 0 ; PREFACE 0 ; TURN ON "{←→"
.PLACE HEADING
{DATE}←AUTOMATIC VETERINARIAN→{SECTION!}
←{SUBTITLE!}
.PLACE FOOTING
{IF ODD PAGE THEN "→"}{PAGE!}
.⊃
$END
$SEC FOOTNOTES
Every column of every area has two portions, the ↓_calf_↓ and the ↓_foot_↓.
During preparation of the calf, paragraphs can be sent to the foot. A
column is considered full when the sum of the lines in the calf and the
foot exceeds the height of the area.
You can not declare Portion FOOT nor do a RECEIVE for it. The
compiler automatically declares a FOOT for each area you declare, and
does a RECEIVE for it after each line is placed in the calf. Your only
foothold is the command "SEND FOOT".
Example:
$BEG TURN OFF "←{"
.COUNT FOOTNOTE INLINE IN PAGE PRINTING "(i)"
.AT "$$" ENTRY "*" ⊂ NEXT FOOTNOTE ; ! ;
.SEND FOOT ⊂ TURN ON "{" PREFACE 1 SPREAD←1 INDENT 0,0
{!} ENTRY
.BREAK ⊃ ⊃
$END
$COUNT FOOTNOTE INLINE IN PAGE PRINTING ⊂"*********"[1 TO FOOTNOTE]⊃
$AT "$$" ENTRY "*" ⊂ NEXT FOOTNOTE ; ("↑"&!) ;
$SEND FOOT ⊂ TURN ON "{" PREFACE 1 SPREAD←1 INDENT 0,0
{!}) ENTRY { BREAK ⊃ ⊃
An example$$Thanks are due to Profs. G.I. Wish and O.U. Kidd of
Steady State University for this example.* of the use of the "α$$" signal response is:
$BEG
...have been shown α$$Abelwitz has obtained
similar results in his experiments with
hippopotami.*.
$END CONTINUE
which will print in the calf:
$INS
...have been shown (iv).
and in the foot:
$BEG
(iv) Abelwitz has obtained similar results
in his experiments with hippopotami.
$END
There is an implicit BEGIN FILL ; ... END around footnotes.
$PORTION APPENDICES
$SEND CONTENTS ⊂ IF LINES < 10 THEN NEXT PAGE ; SKIP 3 ;
$BEGIN CENTER
APPENDICES
----------
$END ⊃
$MACRO APP(NAME) ⊂ NEXT PAGE NEXT APPENDIX BEGIN CENTER
$CURRSS ← NULL ; SECNAME ← "PUB" ;
APPENDIX {!}
$SKIP
NAME
$SKIP ; SECNAME ← "NAME" ;
$END
$SEND CONTENTS ⊂ IF LINES < 10 THEN NEXT PAGE ; SKIP 2 ;
{APPENDIX!}∂(10)NAME
$SKIP 1 ;
$⊃ SEND INDEX ⊂ }∧NAME%{PAGE!}∨{
$ ⊃ ⊃;
$MACRO SAPP(NAME,LBL) ⊂ IF LINES<8 THEN NEXT PAGE LBL NEXT SUBAPPENDIX!
$CURRSS ← SUBAPPENDIX! ;
$IF FIRSTSS = NULL THEN FIRSTSS ← CURRSS ELSE LASTSS ← CURRSS ;
$BEGIN NOFILL INDENT 0,0 SKIP 2
{!} ↓_NAME_↓
$END
$SEND CONTENTS ⊂
∂(15){SUBAPPENDIX!}∂(25)NAME\∞ ∞.∞ →#{PAGE!}
$⊃ SEND INDEX ⊂ }∧NAME%{PAGE!}∨{
$ ⊃ ⊃;
$COUNT APPENDIX PRINTING "A"
$COUNT SUBAPPENDIX IN APPENDIX PRINTING "!.1"
$APP THOROUGHLY EXPLAINED EXAMPLES
$SAPP SECTIONING MACROS
At the beginning of each section, it is customary to perform the following
ritual:
$beg
<<1>> Begin a fresh page
<<2>> Count up the section number
<<3>> Print the section number and name
<<4>> Skip a few lines
<<5>> Send the section number, name, and page number to the CONTENTS
$end
See the document PUBMAC.TES[UP,DOC] for a description of
the macros STANDARD FRONT and STANDARD BACK, which do all these things
for you. If you want to define your own macros, read on.
A macro to perform all the steps listed above <<commented for reference>> is:
$BEG QUIET
.MACRO SEC(NAME)
.<<1>> NEXT PAGE
.<<2>> NEXT SECTION
.<<3>> ONCE CENTER
↓_SECTION {!}_↓ -- ↓_NAME_↓
.<<4>> SKIP 3
.<<5>> SEND CONTENTS ⊂
{!}\\NAME→{PAGE!}{⊃⊃
$END
A sample call on this macro is:
$INS
.SEC SPECIAL FEATURES
At the beginning of each subsection, a similar macro can be called.
The one below prints the subsection name on a line by itself
but prints the subsection number at the beginning of the first line
of the first paragraph of the subsection. It makes sure that there are
enough lines for all this to be contiguous; if not, it first goes to a
new page.
Finally, it allows the macro call to specify a label to be used in
cross-references to this subsection.
$BEG QUIET
.MACRO SS(NAME, LABEL) ⊂
.IF LINES < 10 THEN NEXT PAGE
.SKIP 2
.LABEL NEXT SUBSECTION
.ONCE NOFILL
NAME
.SEND CONTENTS ⊂
\{!}\\NAME→{PAGE!}{⊃⊃
{SUBSECTION!}. {⊃
$END
The second argument is optional. If present, it must include a colon at the end:
$INS
.SS MISCELLANEOUS FEATURES,MISC:
which would define the label MISC and output something like this:
$BEG
MISCELLANEOUS FEATURES
33-7. This is the first line of the paragraph that follows.
$END
$SAPP SAMPLE TABLE OF CONTENTS
The following ≤CONTENTS≥ portion expects a file generated by the SENDs in the
SEC and SS macros shown above.
$BEG
.PORTION CONTENTS
.NOFILL
.TABS 12, 20, 30
.SKIP 2
.RECEIVE
$END
and might output:
$BEG NOFILL TABS 12,20,30
↓_SECTION_↓\↓_Subsection_↓→↓_PAGE_↓
$SKIP 2
1\\INTRODUCTION→3
\1-1\\PURPOSE→3
\1-2\\APPROACH→3
2\\BACKGROUND→11
\2-1\\HISTORY→11
\2-2\\SIMILAR WORK→13
\2-3\\STATE-OF-THE-ART→19
$END
Notice that nearly all formatting is accomplished in the SEND template.
Long titles will not be handled by the portion declared above. Instead,
FILL mode must be used.
The following declarations are approximately what was used to produce
the table of contents of this manual.
$BEG
.PORTION CONTENTS
.FILL CRBREAK NOJUST
.INDENT 0, 35, 10
.TABS 10, 15, 25
.SKIP 2
.RECEIVE
$END
$SAPP ONE-LEVEL INDEXES,INDEXIX:
There is presently no way to have a phrase ≤index≥ed automatically
every time it occurs.
PUB now requires that you mark each phrase to be indexed at every
occurrence that you wish to be referenced. The AT <signal characters>
response is particularly useful for this purpose.
Choose a character or
a pair of characters that will never appear in the text of your manuscript;
for example "%<". This will be your signal that the next phrase is to be
indexed. Then choose a character that will never appear in such a phrase;
for example, ">". This will be your end-of-phrase delimiter.
Suppose you would like the phrase "Simple variables" to be indexed. Find
each occurrence of this phrase in your manuscript and surround it by your
chosen characters:
$SKIP
$INS
Nothing warms the heart like %<simple variables>. We
Your favorite text editor may be of some help in this task; however,
watch out for a phrase that is broken across two lines: the editor will
miss it if your search string is too stringent.
Suppose you would like your index to look something like this:
$BEG
signed constants 8.0
significant digits 10.3, 10.7
signs 2.4, 3.7
simple variables 8.1, 20.8, 20.11
$END
Now you need to declare a signal response
see {YON TEXTRESP}) at the beginning of your manuscript:
$BEG TURN OFF "{"
.AT "%<" PHRASE ">" ⊂ }PHRASE{
.SEND INDEX ⊂ }∧<PHRASE>{PAGE!}∨{⊃⊃
$END
This will respond to each occurrence in the text of the signal
"%<". The characters that follow this signal, up to but not including
the next ">", will be substituted in the body of the template for every occurrence
of the word PHRASE. Then the body of the template will be surrounded by "α{...}" and
embedded in the text, replacing all characters from
and including "%<" to and including ">". The effect in the example above would be:
$BEG TURN OFF "{"
Nothing warms the heart like { }simple variables{
.SEND INDEX ⊂ }∧<simple variables>{PAGE!}∨{⊃}. We
$END
SEND causes the current PAGE! to be
substituted in the SEND template. Thus, the characters sent to the generated
file will be:
$BEG QUIET
}∧<simple variables>2.6∨{
$END
In the generated file, each index entry is signalled by the character pair
"∧<, followed by the phrase, followed by ">", followed by the page number and "∨".
You may of course choose your own delimiters.
They will be recognized by the following
signal response that appears in PORTION INDEX:
$BEG QUIET
.PORTION INDEX
.NOFILL
.LETTER ← PHR ← NULL
.AT "∧<" PHRASE ">" PGNO "∨" ⊂
.IF "PHRASE" = PHR THEN START },#PGNO{ END
.ELSE START COMMENT NEW PHRASE, GO TO A NEW LINE ;
. IF ↑LETTER = ↑"PHRASE"[1] THEN BREAK
. ELSE SKIP 1 ;
PHRASE##PGNO{
. PHR ← "PHRASE" ; LETTER ← "PHRASE"[1] ;
. END ⊃ ; COMMENT END SIGNAL RESPONSE ;
.RECEIVE "<>" ; COMMENT ALPHABETIZE BEFORE READING ;
$END
RECEIVE will alphabetize the entries.
The "AT" signal response will analyze each
entry and make a couple of checks before outputting it:
(1)#If the phrase is the same as the one just printed, it simply appends the page
number of the new entry to the last line printed. For example, if the alphabetized
file contained:
$INS
...∧<Signs>2.4∨α{}∧<Signs>3.7∨...
then the index would include:
$INS
Signs 2.4, 3.7
(2) Else, if the first letter of this and the previous phrase are the same, it goes
to the next line; else, it skips a line. Thus, between the A's (and a's) and the
B's (and b's) there will be a blank line. Then, it prints both the phrase and the
page number.
$SAPP TWO-LEVEL INDEXES
A "two-level index" divides some phrases into two parts: a "generic" part
and a "specific" part, e.g.:
$BEG
compilers,
Algol 13, 15
Fortran 18
LISP 22
SAIL 15
computers,
analog 29
digital 10, 64, 80
consoles 16, 25
$END
In the phrase "Fortran compilers", "Fortran" is the specific part and "compilers"
is the generic part.
This time we will approach the problem analytically instead of synthetically.
There are two kinds of entries: one part and two part If two entries have
the same generic part (e.g., "computers"), then the generic part should print only once.
As PORTION INDEX receives each entry, it must compare it with the preceding
entry. Say that the generic part of the preceding
entry was WASL and the specific part
was WASR (WASL was thus printed on the Left and WASR on the Right). The generic
part of the current entry is L and the specific part is R. If WASL and L are
different, a whole new generic entry is to be printed. Otherwise, if WASR and R
are different, a new specific entry is to be printed. Otherwise, a new page
number is to be added to the last entry printed.
As an extra feature in this
index, we will not print the same page number twice on the same line, i.e.,
twice in a row.
Thus, an additional variable, WASP, will be needed to remember the page number
last printed.
Furthermore, if the entry has no specific part (see "consoles" in the above example),
the page numbers will be printed on the same line as the generic part.
The PORTION INDEX that follows assumes that the generated file has
entries of the form:
$INS
"<" generic-part "/" specific-part ">" page-number "%"
where the specific-part can be empty.
$BEG QUIET
.PORTION INDEX
.WASL ← WASR ← WASP ← NULL ;
.NOFILL ; TABS 6 ;
.AT "<" L "/" R ">" PGNO "%" ⊂
. IF ↑WASL[1] ≠ ↑"L"[1] THEN SKIP 1 ; <<1ST LETTER DIFFERENT>>
. IF WASL ≠ "L" THEN
. START "NEW GENERIC" BREAK ;
L{IF "R"≠NULL THEN START "WITH SPECIFIC PART" },
\R##{ END "WITH SPECIFIC PART" ; }PGNO{
. END "NEW GENERIC"
. ELSE IF WASR ≠ "R" THEN
. START "NEW SPECIFIC" BREAK ;
\R##PGNO{ END "NEW SPECIFIC"
. ELSE IF WASP ≠ "PGNO" THEN START },PGNO{ END
. ⊃ ;
.RECEIVE "<>" ;
$END
To create the generated file for PORTION INDEX requires a signal response such as:
$BEG QUIET
.AT "%<" SPECIFIC "/" GENERIC ">" ⊂
. IF "SPECIFIC"≠NULL THEN START }SPECIFIC { END ;
. }GENERIC{ ; comment print SPECIFIC and GENERIC in the text ;
. SEND INDEX ⊂ }<GENERIC/SPECIFIC>{PAGE!}%{⊃ ;
. ⊃ ;
$END
Every phrase to be sent to the index should be bracketed as follows where it
appears in the manuscript:
$BEG
that there are more %<Algol/compilers> than Algol users ...
the world's leading expert on %</consoles>.
$END
$SAPP KWIC INDEXES
This one is easy. The desired output is:
$BEG
writers of ↓_compilers_↓ often balk 16
The XYZ ↓_compilers_↓ 35
certain Algol ↓_compilers_↓ 8
↓_compilers_↓ I've known 41
IBM ↓_computer_↓ 72
uses of the ↓_computer_↓ in government 64
$END
At the end of the manuscript:
$BEG QUIET
.PORTION KWIC
.NOFILL TABS 30
.AT "<" KEY "/" PRE "/" POST ">" PGNO "%" ⊂
→PRE\#↓_KEY_↓#POST→PGNO
.⊃
.RECEIVE "<>"
$END
At the beginning:
$BEG QUIET
.AT "%<" PRE "≤" KEY "≥" POST ">" ⊂
.}PREβKEYβPOST{
.SEND KWIC ⊂
. }<KEY/{
. "PRE"[∞-25 TO ∞] }/{
. "POST"[1 TO 30-LENGTH("KEY")] }/{
. PAGE! }%{
. ⊃ ; ⊃ ;
$END
Each phrase to be indexed is bracketed as follows:
$BEG QUIET
It is said that %<writers of ≤compilers≥ often balk> at
The last %<IBM ≤computer≥> we bought was
$END
$COUNT PAGE PRINTING "I" ;
$PORTION INDEX
$CURRSS ← NULL ; SECNAME ← "PUB" ;
$BEGIN CENTER
SUBJECT AND COMMAND INDEX
$SKIP 1
(References are to Page numbers)
$END
$SECNAME ← "INDEX" ;
$LETTER ← PHR ← PG ← NEWPHR ← NULL ;
$AT "∧" PHRASE "%" PGNO "∨" ⊂
$NEWPHR ← ↑"PHRASE" ;
$IF LETTER ≠ NEWPHR[1] THEN SKIP 1 ;
$IF NEWPHR ≠ PHR THEN START BREAK }PHRASE PGNO{ END
$ELSE IF "PGNO" ≠ PG THEN START }, PGNO{ END ;
$PHR ← NEWPHR ; LETTER ← PHR[1] ; PG ← "PGNO" ; ⊃
$BEGIN
$AREA TWOTXT LINES 9 TO 51 IN 2 COLUMNS 3 APART
$PLACE TWOTXT
$FILL CRBREAK NOJUST INDENT 0,3,0 PREFACE 0 RETAIN
$RECEIVE "∧%"
$END
$COUNT PAGE PRINTING "i"
$PORTION CONTENTS
$CURRSS ← NULL ; SECNAME ← "PUB" ;
$BEGIN CENTER
TABLE OF CONTENTS
----- -- --------
$END
$SKIP
$BEGIN NOFILL INDENT 0,0,0
SECTION→PAGE
$END
$SKIP 1
$SECNAME ← "TABLE OF CONTENTS"
$BEGIN FILL CRBREAK NOJUST PREFACE 0
$TABS 36,39,42,45,48,51,54,57,60,63 INDENT 0,35,10
$RECEIVE
$SKIP 2
∂(10)SUBJECT AND COMMAND INDEX\∞ ∞.∞ →###I
$END